package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.chargecalc.mchntfee.CalcMchntFee;
import cc.rengu.chargecalc.mchntfee.model.CalcMchntFeeBean;
import cc.rengu.chargecalc.mchntfee.model.CalcMchntFeeResultBean;
import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.*;
import cc.rengu.igas.momp.common.dao.impl.*;
import cc.rengu.igas.momp.common.entity.*;
import cc.rengu.igas.momp.common.enums.*;
import cc.rengu.igas.momp.common.util.MompAmountUtil;
import cc.rengu.igas.momp.common.util.MompDateUtil;
import cc.rengu.igas.momp.facade.bean.PaymentOrderMchntFeeDiscountInfoBean;
import cc.rengu.igas.momp.facade.request.ComboMchntFeeDiscountRequest;
import cc.rengu.igas.momp.facade.response.ComboMchntFeeDiscountResponse;
import cc.rengu.jradp.mods.dbs.Database;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.base.StringUtil;
import com.alibaba.fastjson.JSONObject;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author : liujinan
 * @version 1.0.0
 * @date 2020/4/27
 * @Description: 手续费优惠接口实现
 */
public class ComboMchntFeeDiscountService extends RadpService {

    private String globalInstId;
    private String globalTraceNo;
    private String globalTxnDate;
    private String globalTxnTime;
    private String globalTimeStamp;
    /**
     * 订单流水信息-只用作接口处理异常，或者无优惠信息时，订单流水表的登记
     */
    private TMTxnOrder tmTxnOrder;
    /**
     * 流程是否正常标志
     */
    private boolean procNormalStatus;
    /**
     * 手续费营销活动统计表
     */
    private List<TMStatMfd> statMfdList;
    /**
     * 手续费营销活动单日统计表
     */
    private List<TMStatMfdDay> statMfdDayList;
    private BigDecimal zero = BigDecimal.ZERO;
    /**
     * 是否设置了商户结算账户为对公户不允许参加营销活动
     */
    private static final String MOMP_DIFFERENTIATE_SETTLEACCTTYPE = "MOMP_DIFFERENTIATE_SETTLEACCTTYPE";
    /**
     * 新商户入驻时间是否区分15号之前还是之后
     */
    private static final String MOMP_DISTINGUISH_MIDDLE_OF_MONTH = "MOMP_DISTINGUISH_MIDDLE_OF_MONTH";
    /**
     * 东营行机构代码
     */
    private static final String INST_ID_DY = "812";
    /**
     * 东营行新商户重复入网校验手续费优惠额度
     */
    private static final String DISCOUNT_AMOUNT = "40";
    /**
     * 分期类型
     */
    private String stageType = "";
    /**
     * 分期期数
     */
    private String stageNum = "";
    /**
     * 分期code
     */
    private String stageCode = "";

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        try {
            ComboMchntFeeDiscountRequest comboMchntFeeDiscountRequest = new ComboMchntFeeDiscountRequest();
            ConvertUtil.convertOutput(comboMchntFeeDiscountRequest);

            ComboMchntFeeDiscountResponse comboMchntFeeDiscountResponse = new ComboMchntFeeDiscountResponse();
            comboMchntFeeDiscountResponse.setHeader(comboMchntFeeDiscountRequest.getHeader());
            BizResponse<ComboMchntFeeDiscountResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(comboMchntFeeDiscountResponse);

            //接口请求报文检查,及全局变量赋值
            checkRequestMessage(comboMchntFeeDiscountRequest);

            // 调用处理流程
            BizResponse<ComboMchntFeeDiscountResponse> bizResponseNew = comboMchntFeeDiscount(xmlTreeUtil, comboMchntFeeDiscountRequest, comboMchntFeeDiscountResponse);

            ConvertUtil.convertInput(bizResponseNew.getResult());
        } catch (BizException e) {
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e));
            }
        }
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 手续费优惠
     *
     * @param comboMchntFeeDiscountRequest
     * @param comboMchntFeeDiscountResponse
     * @param xmlTreeUtil                   内部XML树
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/11
     */
    private BizResponse<ComboMchntFeeDiscountResponse> comboMchntFeeDiscount(XmlTreeUtil xmlTreeUtil, ComboMchntFeeDiscountRequest comboMchntFeeDiscountRequest, ComboMchntFeeDiscountResponse comboMchntFeeDiscountResponse) throws Exception {
        BizResponse<ComboMchntFeeDiscountResponse> bizResponse = new BizResponse<>();

        //机构标识
        String instId = comboMchntFeeDiscountRequest.getHeader().getInstId();
        //获取接口上送的手续费减免优惠信息订单列表
        List<PaymentOrderMchntFeeDiscountInfoBean> feeOrderDetailList = comboMchntFeeDiscountRequest.getFeeOrderDetailList();
        //业务产品代码
        String bizProdCode = comboMchntFeeDiscountRequest.getBizProdCode();
        //商户订单号
        String mchntOrderId = comboMchntFeeDiscountRequest.getMchntOrderId();
        //订单总金额
        String transAmt = comboMchntFeeDiscountRequest.getTransAmt();
        //用户编号
        String userId = comboMchntFeeDiscountRequest.getUserId();

        List<PaymentOrderMchntFeeDiscountInfoBean> returnFeeOrderDetailList = new ArrayList<>();

        //待插入数据库的订单明细列表
        List<TMTxnOrderDet> tmTxnOrderDetList = new ArrayList<>();

        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();
        try {
            //接口上送的列表为空
            if (null == feeOrderDetailList || feeOrderDetailList.isEmpty()) {
                rglog.info("<{}>, mchntOrderId=<{}>", RespCodeEnum.NO_AVAILABLE_DATA_TO_PROCESS_ERROR.getRespDesc(), mchntOrderId);
                throw new BizException(RespCodeEnum.NO_AVAILABLE_DATA_TO_PROCESS_ERROR.getRespCode(), RespCodeEnum.NO_AVAILABLE_DATA_TO_PROCESS_ERROR.getRespDesc());
            } else {
                rglog.info("有手续费订单明细，开始处理手续费优惠...");
                //循环遍历上送的手续费订单明细
                for (PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail : feeOrderDetailList) {
                    rglog.info("-----------------------商户<{}> 手续费优惠处理流程开始----------------------------", feeOrderDetail.getMchntNo());
                    // 检查上传字段 不能为负数
                    checkFeeOrderDetailFieldHasNegativeNumber(feeOrderDetail);

                    //循环遍历时的所有信息都存储在mcMchntFeeDiscountTransData中，以便使用
                    McMchntFeeDiscountTransData mcMchntFeeDiscountTransData = new McMchntFeeDiscountTransData();
                    mcMchntFeeDiscountTransData.setMchntOrderId(mchntOrderId);
                    mcMchntFeeDiscountTransData.setTransAmt(transAmt);
                    mcMchntFeeDiscountTransData.setUserId(userId);
                    mcMchntFeeDiscountTransData.setTransDate(globalTxnDate);
                    mcMchntFeeDiscountTransData.setMchntFeeReceivable(feeOrderDetail.getMchntFeeReceivable());
                    mcMchntFeeDiscountTransData.setMchntFeeReceivableRate(feeOrderDetail.getMchntFeeReceivableRate());
                    mcMchntFeeDiscountTransData.setMchntFeeDiscountMethod(feeOrderDetail.getMchntFeeDiscountMethod());
                    mcMchntFeeDiscountTransData.setFeeInputMode(feeOrderDetail.getFeeInputMode());
                    mcMchntFeeDiscountTransData.setFeeType(feeOrderDetail.getFeeType());
                    mcMchntFeeDiscountTransData.setCalMchntFeeBizProdCode(feeOrderDetail.getBizProdCode());
                    //商户优惠交易金额  初始值为上送的商户清算金额
                    mcMchntFeeDiscountTransData.setMchntFeeDiscountTransAmt(feeOrderDetail.getMchntSettleAmt());
                    //获取商户号
                    String detailMchntNo = feeOrderDetail.getMchntNo();
                    mcMchntFeeDiscountTransData.setMchntNo(detailMchntNo);
                    //查询商户基本信息
                    rglog.info("交易流水号<{}>,查询商户<{}>基本信息信息开始", globalTraceNo, detailMchntNo);
                    MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
                    TBMchntBaseInfo mchntBaseInfo = mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(instId, detailMchntNo);
                    if (null == mchntBaseInfo) {
                        //查询不到商户信息，流程结束
                        rglog.error("查询商户基本信息信息失败, INST_ID=<{}>, MCHNT_NO=<{}>", instId, detailMchntNo);
                        throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
                    }
                    //商户基本信息存储到mcMchntFeeDiscountTransData中
                    copyMchntBaseInfo(mcMchntFeeDiscountTransData, mchntBaseInfo);
                    String transDate = mcMchntFeeDiscountTransData.getTransDate();

                    //商户性质
                    String mchntType = mchntBaseInfo.getMchntType();
                    //独立营销活动标识
                    String idpdCmavyFlg = mchntBaseInfo.getMarketFlag();
                    //连锁商户号
                    String chainMchntNo = mchntBaseInfo.getChainMchntNo();
                    //是否独立维护商户资料
                    String independentDataFlag = mchntBaseInfo.getIndependentDataFlag();
                    if (CommonConstant.YES.equals(independentDataFlag) && MchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntType) && CommonConstant.ZERO_COMMON_CONSTANT.equals(idpdCmavyFlg)) {
                        rglog.info("商户<{}> 商户类型为11:连锁商户门店，商户独立营销活动标识为<{}> 是否独立维护商户资料<{}> 获取营销活动时需根据上级商户<{}> 获取!", detailMchntNo, idpdCmavyFlg, independentDataFlag, chainMchntNo);
                        detailMchntNo = chainMchntNo;
                        //查询上级商户的基本信息
                        TBMchntBaseInfo chainMchntBaseInfo = mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(instId, detailMchntNo);
                        if (null == chainMchntBaseInfo) {
                            //查询不到商户信息，流程结束
                            rglog.error("查询当前商户<{}>的上级商户<{}>基本信息信息失败!", feeOrderDetail.getMchntNo(), detailMchntNo);
                            throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
                        }
                        //商户基本信息存储到mcMchntFeeDiscountTransData中
                        copyMchntBaseInfo(mcMchntFeeDiscountTransData, chainMchntBaseInfo);
                    } else {
                        rglog.info("商户<{}> 是否独立维护商户资料<{}> 商户类型为<{}>无需判断独立营销活动标识，均使用当前商户号计算营销！", detailMchntNo, independentDataFlag, mchntType);
                    }

                    //判断机构是否限定了商户结算账户是对公户的商户不允许参加营销活动
                    MompSysParamMapper mompSysParamMapper = new MompSysParamMapperImpl();
                    SysParam sysParam = mompSysParamMapper.getSysParamInfoBuyPrimaryKey(globalInstId, MOMP_DIFFERENTIATE_SETTLEACCTTYPE, MOMP_DIFFERENTIATE_SETTLEACCTTYPE);
                    if (null != sysParam) {
                        //判断设置的标志位是限制对公户不能参加，还是不限制对公户不能参加
                        String paramValue = sysParam.getParamValue();
                        if (CommonConstant.YES.equals(paramValue)) {
                            //如果限定了，则查询商户的结算账户
                            rglog.info("机构<{}>限定了结算账户为对公户的商户不允许参加手续费营销活动，继续判断商户<{}> 的结算账户信息!", instId, detailMchntNo);
                            /*商户结算信息正式表*/
                            McMchntAcctInfoMapper mcMchntAcctInfoMapper = new McMchntAcctInfoMapperImpl();
                            MchntAcctInfo mchntAcctInfo = mcMchntAcctInfoMapper.selectMchntAcctInfoByPrimaryKey(globalInstId, detailMchntNo, "*", FundTypeEnum.SETTLE_TYPE.getFundCode());
                            if (null != mchntAcctInfo) {
                                //结算账户类型
                                String settleAcctType = mchntAcctInfo.getSettleAcctType();
                                if (AcctTypeEnum.OWN_CORPORATE_ACCOUNT.getAcctType().equals(settleAcctType) ||
                                        AcctTypeEnum.OTHER_CORPORATE_ACCOUNT.getAcctType().equals(settleAcctType)) {
                                    //本商户的结算账户为对公户，不允许参加活动
                                    rglog.error("商户<{}> 结算账户类型<{}> 机构设置了结算账户为对公户的商户不允许参加手续费营销活动，故此商户不允许参加此活动!", instId, settleAcctType);
                                    recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                                    continue;
                                }
                            } else {
                                rglog.error("商户<{}> 未获取到结算账号信息，异常!", detailMchntNo);
                                recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                                continue;
                            }
                        }
                    }

                    //查询商户手续费减免达标数据统计表数据,看是否商户已经存在表中,来判断是否参加营销活动
                    rglog.info("交易流水号<{}>,机构<{}>的商户<{}>查询商户手续费减免达标数据统计表", globalTraceNo, globalInstId, detailMchntNo);
                    TMStatMfdCriteria tmStatMfdCriteria = selectTMStatMfdCriteriaByUsingMchntNoAndDateRange(instId, detailMchntNo, transDate);

                    if (null == tmStatMfdCriteria) {
                        rglog.info("未找到机构<{}>的商户<{}>的手续费减免达标数据统计,需进一步判断商户是否是新增商户!", instId, detailMchntNo);
                        //如果查询失败，进一步确定商户是否是手续费营销活动期间新增的商户

                        //通过签约机构sign_inst_id查询营销活动机构信息表，判断所属机构是否有正在进行的手续费优惠活动
                        int returnResult = getMchntFeeDiscountOngoing(mcMchntFeeDiscountTransData);
                        //0:成功，流程继续  1:本次结束，继续下一次
                        if (CommonConstant.ONE == returnResult) {
                            //记录本订单明细没有手续费优惠，添加到返回列表
                            recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                            continue;
                        }
                        if (CommonConstant.PROCESS_SUCCESS != checkMchntMcStatus(mcMchntFeeDiscountTransData)) {
                            rglog.error("机构<{}>的新商户参与手续费优惠营销活动<{}> 活动状态<{}>信息校验失败!", instId, mcMchntFeeDiscountTransData.getMcNo(), mcMchntFeeDiscountTransData.getMcStatus());
                            recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                            continue;
                        }
                    } else {
                        //将手续费减免达标数据统计表转存到对象mcMchntFeeDiscountTransData
                        convertMchntFeeDiscountCriteria(tmStatMfdCriteria, mcMchntFeeDiscountTransData);
                        //查询到达标数据统计表，判断商户退出状态和达标状态
                        int exitFlagAndCriteriaFlag = checkExitFlagAndCriteriaFlag(tmStatMfdCriteria);
                        if (CommonConstant.ONE == exitFlagAndCriteriaFlag) {
                            //记录本订单明细没有手续费优惠，添加到返回列表
                            recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                            continue;
                        }

                        String mcNo = mcMchntFeeDiscountTransData.getMcNo();
                        rglog.info("机构<{}>的商户<{}>的营销活动<{}>，未退出优惠活动，流程继续", globalInstId, detailMchntNo, mcNo);

                        //获取营销活动基本信息
                        rglog.info("机构<{}>的商户<{}>，开始获取营销活动<{}>的基本信息", globalInstId, detailMchntNo, mcNo);
                        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo = getMchntFeeDiscountMcInfo(instId, mcNo);
                        if (null == tmMcMchntFeeDiscountInfo) {
                            rglog.error("机构<{}>的商户<{}>未获取到商户手续费优惠营销活动信息!", instId, detailMchntNo);
                            throw new BizException(RespCodeEnum.GET_MCHNT_FEE_DISCOUNT_MC_LIST_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_FEE_DISCOUNT_MC_LIST_ERROR.getRespDesc());
                        }

                        //将手续费优惠营销活动信息转存到对象mcMchntFeeDiscountTransData
                        copyTMMcMfdInfo(mcMchntFeeDiscountTransData, tmMcMchntFeeDiscountInfo);

                        if (CommonConstant.PROCESS_SUCCESS != checkMchntMcStatus(mcMchntFeeDiscountTransData)) {
                            rglog.error("机构<{}>的存量商户参与手续费优惠营销活动<{}> 活动状态<{}> 信息校验失败!", instId, mcMchntFeeDiscountTransData.getMcNo(), mcMchntFeeDiscountTransData.getMcStatus());
                            recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                            continue;
                        }
                        //达标后手续费优惠规则-达标后的交易通过返现营销的不在联机计算手续费优惠
                        if (CommonConstant.FEE_POSTPONE_DISCOUNT_FLAG.equals(tmMcMchntFeeDiscountInfo.getAfterFlag()) &&
                                CommonConstant.MCHNT_OLD_FLAG.equals(mcMchntFeeDiscountTransData.getNewMchntFlag())) {
                            rglog.error("机构<{}>存量商户<{}>-达标后手续费优惠规则-达标后的交易通过返现营销的不在联机计算手续费优惠!", globalInstId, detailMchntNo);
                            //记录本订单明细没有手续费优惠，添加到返回列表
                            recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                            continue;
                        }
                    }
                    //使用payType判断该营销活动是否是支持的类型
                    McProductInfoMapper mcProductInfoMapper = new McProductInfoMapperImpl();
                    rglog.info("机构<{}>的商户<{}>的营销活动<{}>开始查询是否支持营销活动产品<{}>", instId, detailMchntNo, mcMchntFeeDiscountTransData.getMcNo(), bizProdCode);
                    if (null == mcProductInfoMapper.selectMcProductInfoByPrimaryKey(instId, mcMchntFeeDiscountTransData.getMcNo(), bizProdCode)) {
                        rglog.error("机构<{}>的商户<{}>的营销活动<{}>不支持营销产品<{}>", instId, detailMchntNo, mcMchntFeeDiscountTransData.getMcNo(), bizProdCode);
                        //记录本订单明细没有手续费优惠，添加到返回列表
                        recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                        continue;
                    } else {
                        //根据以上标记的newMchntFeeFlag判断是否需要获取商户手续费优惠规则
                        String newMchntFeeFlag = mcMchntFeeDiscountTransData.getNewMchntFeeFlag();
                        //不是免手续费，需要取商户手续费优惠规则以便后续计算手续费优惠金额，当1时为新商户全免手续费,0：存量商户，2：新商户按规则计算手续费
                        if (CommonConstant.ZERO_COMMON_CONSTANT.equals(newMchntFeeFlag)) {
                            //获取商户手续费优惠规则,获取手续费优惠上限计算规则,计算手续费优惠上限
                            rglog.info("机构<{}>的商户<{}>的营销活动<{}>开始获取手续费优惠规则", instId, detailMchntNo, mcMchntFeeDiscountTransData.getMcNo());
                            int returnResult = getCalRuleNoAndFeeDiscountLimit(mcMchntFeeDiscountTransData);
                            //0:成功，流程继续  1:本次结束，继续下一次
                            if (CommonConstant.ONE == returnResult) {
                                //记录本订单明细没有手续费优惠，添加到返回列表
                                recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                                continue;
                            }

                            //根据获取到的手续费优惠规则中的优惠类型discount_type计算优惠的手续费
                            rglog.info("机构<{}>的商户<{}>的营销活动<{}>开始计算手续费优惠值...", instId, detailMchntNo, mcMchntFeeDiscountTransData.getMcNo());
                            int getFeeDiscountResult = getFeeDiscount(mcMchntFeeDiscountTransData, feeOrderDetail);

                            //0:成功，流程继续  1:本次结束，继续下一次
                            if (CommonConstant.ONE == getFeeDiscountResult) {
                                //记录本订单明细没有手续费优惠，添加到返回列表
                                recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                                continue;
                            }
                            feeOrderDetail.setMchntFeeDiscountMcNo(mcMchntFeeDiscountTransData.getMcNo());

                            //更新手续费减免活动单日统计表T_M_STAT_MFD_DAY,更新手续费减免活动商户单日统计表T_M_STAT_MFD_MCHNT_DAY
                            updateFeeDiscountReport(comboMchntFeeDiscountRequest, mcMchntFeeDiscountTransData, feeOrderDetail);

                            //判断是否需要更新达标统计表退出标志
                            checkExitFlagAndUpdateTMStatMfdCriteria(mcMchntFeeDiscountTransData);

                            //商户手续费优惠营销活动编号
                            feeOrderDetail.setMchntFeeDiscountMcNo(mcMchntFeeDiscountTransData.getMcNo());
                            //设置实收手续费金额
                            feeOrderDetail.setMchntFeeActual(feeOrderDetail.getMchntFeeActual());
                            //设置手续费优惠金额
                            feeOrderDetail.setMchntFeeDiscount(feeOrderDetail.getMchntFeeDiscount());
                            //设置手续费优惠金额
                            feeOrderDetail.setMchntFeeDiscountMethod(mcMchntFeeDiscountTransData.getMchntFeeDiscountMethod());
                        } else if (CommonConstant.TWO_COMMON_CONSTANT.equals(newMchntFeeFlag)) {
                            //当为新商户按规则计算手续费时的处理
                            rglog.info("机构<{}>的商户<{}>的营销活动<{}> 按照新商户按规则计算手续费优惠，当前商户未达标（如果达标会在达标统计表中存在达标记录）", instId, detailMchntNo, mcMchntFeeDiscountTransData.getMcNo());
                            recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                            continue;
                        } else {
                            //剩余的为1：新商户全免手续费   新商户免手续费时需要检验，周期内，免费的额度是否超限

                            //如果是特殊费率商户，则没有任何手续费优惠
                            if (CommonConstant.FEE_MODE_LADDER.equals(mcMchntFeeDiscountTransData.getFeeInputMode())) {
                                mcMchntFeeDiscountTransData.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT_FEE);
                                mcMchntFeeDiscountTransData.setMchntFeeActual(mcMchntFeeDiscountTransData.getMchntFeeReceivable());
                                rglog.info("商户<{}>的手续费收取方式为  使用现有费率，无手续费优惠", detailMchntNo);
                                //记录本订单明细没有手续费优惠，添加到返回列表
                                recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                                continue;
                            }

                            //设置实收手续费金额
                            mcMchntFeeDiscountTransData.setMchntFeeActual(BigDecimal.ZERO.toString());
                            //设置手续费优惠金额
                            mcMchntFeeDiscountTransData.setMchntFeeDiscount(feeOrderDetail.getMchntFeeReceivable());
                            //设置新商户规则编号为 0
                            mcMchntFeeDiscountTransData.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                            /* 优惠类型-免手续费 */
                            mcMchntFeeDiscountTransData.setDiscountType(CommonConstant.MCHNT_FEE_FREE);
                            /* 优惠力度 */
                            mcMchntFeeDiscountTransData.setDiscount(CommonConstant.MCHNT_FEE_FREE);

                            rglog.info("机构<{}>的商户<{}>的营销活动<{}>开始计算新增商户手续费优惠值...", instId, detailMchntNo, mcMchntFeeDiscountTransData.getMcNo());
                            int getFeeDiscountResult = getNewMchntFeeDiscount(mcMchntFeeDiscountTransData, feeOrderDetail);
                            //0:成功，流程继续  1:本次结束，继续下一次
                            if (CommonConstant.ONE == getFeeDiscountResult) {
                                //记录本订单明细没有手续费优惠，添加到返回列表
                                recordNoDiscountFeeOrderDetail(returnFeeOrderDetailList, feeOrderDetail);
                                continue;
                            }
                            //更新手续费减免活动单日统计表T_M_STAT_MFD_DAY,更新手续费减免活动商户单日统计表T_M_STAT_MFD_MCHNT_DAY
                            updateFeeDiscountReport(comboMchntFeeDiscountRequest, mcMchntFeeDiscountTransData, feeOrderDetail);

                            rglog.info("机构<{}>的商户<{}>的营销活动<{}>新商户全免手续费", instId, detailMchntNo, mcMchntFeeDiscountTransData.getMcNo());
                            //全免手续费，赋值各字段值
                            //商户手续费优惠营销活动编号
                            feeOrderDetail.setMchntFeeDiscountMcNo(mcMchntFeeDiscountTransData.getMcNo());
                            //设置实收手续费金额
                            feeOrderDetail.setMchntFeeActual(mcMchntFeeDiscountTransData.getMchntFeeActual());
                            //设置手续费优惠金额
                            feeOrderDetail.setMchntFeeDiscount(mcMchntFeeDiscountTransData.getMchntFeeDiscount());
                            //设置手续费优惠方式
                            feeOrderDetail.setMchntFeeDiscountMethod(mcMchntFeeDiscountTransData.getMchntFeeDiscountMethod());
                        }
                    }
                    //生成订单明细，并将订单明细添加到订单明细列表
                    TMTxnOrderDet tmTxnOrderDet = generateSingleTxnOrderDetail(comboMchntFeeDiscountRequest, feeOrderDetail, mcMchntFeeDiscountTransData);
                    if (null == tmTxnOrderDet) {
                        rglog.error("机构<{}>的商户<{}>的营销活动<{}>生成订单明细表数据失败！", instId, detailMchntNo, mcMchntFeeDiscountTransData.getMcNo());
                        throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
                    }
                    tmTxnOrderDetList.add(tmTxnOrderDet);

                    //添加到返回的列表中
                    returnFeeOrderDetailList.add(feeOrderDetail);
                }

                //判断订单明细列表是否为空，为空则明细表不登记订单信息，只登记订单流水表信息
                if (null != tmTxnOrderDetList && !tmTxnOrderDetList.isEmpty()) {
                    rglog.info("机构<{}>商户订单号<{}>开始登记订单明细表数据", instId, comboMchntFeeDiscountRequest.getMchntOrderId());
                    //登记订单明细表 T_M_TXN_ORDER_DET
                    recordTxnOrderDetail(tmTxnOrderDetList);
                    rglog.info("机构<{}>商户订单号<{}>开始登记订单流水表数据", instId, comboMchntFeeDiscountRequest.getMchntOrderId());
                    //登记订单流水表T_M_TXN_ORDER
                    recordTxnOrder(comboMchntFeeDiscountRequest, returnFeeOrderDetailList);
                } else {
                    //流程是否正常标志  确保任何情况下订单流水表都有记录存在,登记成功的但是无优惠的订单流水
                    procNormalStatus = true;
                    //登记订单无优惠流水，和上边所有更新或插入处理在一个事务中,不新开始事务处理
                    onlyRecordTxnOrderInfo(xmlTreeUtil, comboMchntFeeDiscountRequest, false);
                }
                //数据都操作完成 ，数据库提交
                dbsUtil.dbsEndTransaction(true);
            }
        } catch (Exception e) {
            rglog.error("商户手续费优惠失败!所有数据库操作回滚!");
            //事务处理失败关闭数据库事务,上边处理流程失败
            dbsUtil.dbsEndTransaction(false);

            //确保任何情况下订单流水表都有记录存在,登记失败的订单流水
            procNormalStatus = false;
            //登记订单无优惠流水，上边处理事务结束，新开始一个事务处理
            onlyRecordTxnOrderInfo(xmlTreeUtil, comboMchntFeeDiscountRequest, true);

            throw new Exception(e);
        }

        bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        comboMchntFeeDiscountResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        comboMchntFeeDiscountResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        comboMchntFeeDiscountResponse.setFeeOrderDetailList(returnFeeOrderDetailList);
        bizResponse.setResult(comboMchntFeeDiscountResponse);

        return bizResponse;
    }

    /**
     * 查询营销活动机构信息表，判断所属机构是否有正在进行的手续费优惠活动
     *
     * @return CommonConstant.ZERO:成功，流程继续  1:本次结束，继续下一次
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/4/30
     */
    private int getMchntFeeDiscountOngoing(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {

        String orgId = mcMchntFeeDiscountTransData.getSignInstId();
        //机构编码
        String instId = mcMchntFeeDiscountTransData.getInstId();
        //商户号
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();

        /* 查询营销活动机构表,判断是否存在当前商户管理机构 */
        MfdMcListInfoInObj mfdMcListInfoInObj = new MfdMcListInfoInObj();
        mfdMcListInfoInObj.setInstId(globalInstId);
        mfdMcListInfoInObj.setOrgId(orgId);
        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoList = mcDetailInfoMapper.selectMfdMcDetailInfoForComboPayment(mfdMcListInfoInObj);
        if (null == tmMcMchntFeeDiscountInfoList || tmMcMchntFeeDiscountInfoList.isEmpty()) {
            rglog.info("未获取到法人机构<{}>的商户<{}>所在机构<{}>的支持新增商户的商户手续费优惠类营销活动信息,该商户无法享受任何商户手续费优惠!", globalInstId, mchntNo, orgId);
            return CommonConstant.ONE;
        }

        /* 判断商户是否重复入网商户 */
        boolean repeatFlag = checkMchntRepeatFlag(mchntNo, mcMchntFeeDiscountTransData.getMchntExpandTime());
        if (repeatFlag) {
            rglog.info("法人机构<{}>的商户<{}>所在机构<{}>为重复入网商户,该商户无法享受任何商户手续费优惠!", globalInstId, mchntNo, orgId);
            return CommonConstant.ONE;
        }

        boolean notDistinguishMiddleOfMonth;
        //判断机构是否设置了区分新商户是15号之前还是之后入驻
        MompSysParamMapper mompSysParamMapper = new MompSysParamMapperImpl();
        SysParam sysParam = mompSysParamMapper.getSysParamInfoBuyPrimaryKey(globalInstId, MOMP_DISTINGUISH_MIDDLE_OF_MONTH, MOMP_DISTINGUISH_MIDDLE_OF_MONTH);
        //如果没有配置（为空）时或者配置的为区分15号时，则进行区分15号之前之后的处理
        if (null != sysParam && CommonConstant.NO.equals(sysParam.getParamValue())) {
            rglog.info("机构<{}>配置了新商户不区分15号之前之后入驻", globalInstId);
            notDistinguishMiddleOfMonth = true;
        } else {
            rglog.info("机构<{}> 新商户区分15号之前之后入驻", globalInstId);
            notDistinguishMiddleOfMonth = false;
        }

        //正在进行的手续费优惠活动只能是一个
        int size = tmMcMchntFeeDiscountInfoList.size();
        rglog.info("查询到机构<{}>的商户<{}>有<{}>条正在进行的支持新增商户的手续费优惠活动，还需继续判断", instId, mchntNo, size);

        //商户入驻时间
        String mchntExpandTime = mcMchntFeeDiscountTransData.getMchntExpandTime();//格式为：yyyy-MM-dd HH:mm:ss.SSS
        String mchntExpandDate = mchntExpandTime.substring(0, 4) + mchntExpandTime.substring(5, 7) + mchntExpandTime.substring(8, 10);

        List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoList1 = new ArrayList<>();

        /* 判断商户入驻日期是否在营销活动期间 */
        for (TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo : tmMcMchntFeeDiscountInfoList) {

            //判断商户是否在营销活动起止日期内入驻
            int returnCode = MompDateUtil.checkDateRange(mchntExpandDate, tmMcMchntFeeDiscountInfo.getMcStartDate(), tmMcMchntFeeDiscountInfo.getMcEndDate());
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.info("法人机构<{}>的商户<{}>的入住日期<{}>并未在营销活动<{}>的起止日期<{}>~<{}>内,判断流程继续!", globalInstId, mchntNo, mchntExpandDate, tmMcMchntFeeDiscountInfo.getMcNo(), tmMcMchntFeeDiscountInfo.getMcStartDate(), tmMcMchntFeeDiscountInfo.getMcEndDate());
                continue;
            }
            //判断当前日期是否已超过该商户入驻日期+优惠月份数(即是否在免手续费周期内)
            if (!checkNewMchntAvailability(mcMchntFeeDiscountTransData, tmMcMchntFeeDiscountInfo, mchntExpandDate, notDistinguishMiddleOfMonth)) {
                rglog.info("法人机构<{}>的商户<{}>的入驻日期<{}>并未在营销活动<{}>的起止日期<{}>~<{}>内,该商户无法享受任何商户手续费优惠!", globalInstId, mchntNo, mchntExpandDate, tmMcMchntFeeDiscountInfo.getMcNo(), tmMcMchntFeeDiscountInfo.getMcStartDate(), tmMcMchntFeeDiscountInfo.getMcEndDate());
                continue;
            }

            /* 判断当前支持新增商户的活动是否指定了商圈，如果指定了商圈，判断当前商户是否在商圈中，如果不在，则当前商户不能参加当前新商户的营销活动 */
            //查询营销活动商户信息表，判断活动是否设置了限定了指定的商圈进行参加
            List<TMMcMchntInfo> tMMcMchntInfoList = selectMcMchntInfoListByMcNo(globalInstId, tmMcMchntFeeDiscountInfo.getMcNo(), CommonConstant.MCHNT_RANGE_TYPE_AREA);
            String mchntArea = mcMchntFeeDiscountTransData.getMchntArea();

            if (null != tMMcMchntInfoList && !tMMcMchntInfoList.isEmpty()) {
                for (TMMcMchntInfo tMMcMchntInfo : tMMcMchntInfoList) {
                    String mcMchntArea = tMMcMchntInfo.getMchntNo();
                    if (mcMchntArea.equals(mchntArea)) {
                        tmMcMchntFeeDiscountInfoList1.add(tmMcMchntFeeDiscountInfo);
                        rglog.info("营销活动<{}>限定了参与活动的商圈<{}>，当前商户所属商圈<{}>,当前活动允许参加!", tmMcMchntFeeDiscountInfo.getMcNo(), tMMcMchntInfo.getMchntNo(), mchntArea);
                    } else {
                        rglog.info("营销活动<{}>限定了参与活动的商圈<{}>，当前商户所属商圈<{}>,当前活动不允许当前商户参加!", tmMcMchntFeeDiscountInfo.getMcNo(), tMMcMchntInfo.getMchntNo(), mchntArea);
                    }
                }
            } else {
                //如果活动未指定参与的商圈，则任何新增商户都可参与
                tmMcMchntFeeDiscountInfoList1.add(tmMcMchntFeeDiscountInfo);
                rglog.info("营销活动<{}>未限定参与活动的商圈,当前商户可以参加当前活动!", tmMcMchntFeeDiscountInfo.getMcNo());
            }
        }
        List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoAfterJudgeMchntNature = new ArrayList<>();
        /* 判断活动是否区分商户性质参加 */
        JudgeMcDiscriminateMchntNature(tmMcMchntFeeDiscountInfoList1, tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, mcMchntFeeDiscountTransData);

        /* 选取支持免手续费优惠时间最长的营销活动免手续费 */
        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo;
        if (CommonConstant.ZERO < tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.size()) {
            tmMcMchntFeeDiscountInfo = tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.stream().max(Comparator.comparing(TMMcMchntFeeDiscountInfo::getRemark1)).get();
            //选取到免手续费时间最长的营销活动
            rglog.info("法人机构<{}>的商户<{}>的入住日期<{}>在营销活动<{}>的起止日期<{}>~<{}>内,且免手续费周期<{}>,时间最长！",
                    globalInstId, mchntNo, mchntExpandDate, tmMcMchntFeeDiscountInfo.getMcNo(), tmMcMchntFeeDiscountInfo.getMcStartDate(), tmMcMchntFeeDiscountInfo.getMcEndDate(), tmMcMchntFeeDiscountInfo.getNewMchntPeriod());
        } else {
            rglog.info("法人机构<{}>的商户<{}>未找到适合的支持新增商户的营销活动,该商户无法享受任何商户手续费优惠!", globalInstId, mchntNo);
            return CommonConstant.ONE;
        }


        rglog.info("机构<{}>的商户<{}>有正在进行的手续费优惠活动<{}>,新商户免手续费", instId, mchntNo, tmMcMchntFeeDiscountInfo.getMcNo());
        //新商户全免手续费
        mcMchntFeeDiscountTransData.setNewMchntFeeFlag(CommonConstant.ONE_COMMON_CONSTANT);

        //为新增商户计算商户手续费减免达标数据统计表中数据
        TMStatMfdCriteria tmStatMfdCriteria = processNewMchntCriteriaData(mcMchntFeeDiscountTransData, tmMcMchntFeeDiscountInfo, mchntExpandDate, notDistinguishMiddleOfMonth);
        if (null == tmStatMfdCriteria) {
            rglog.info("法人机构<{}>的商户<{}>的入住日期<{}>并未在营销活动<{}>的起止日期<{}>~<{}>内,该商户无法享受任何商户手续费优惠!", globalInstId, mchntNo, mchntExpandDate, tmMcMchntFeeDiscountInfo.getMcNo(), tmMcMchntFeeDiscountInfo.getMcStartDate(), tmMcMchntFeeDiscountInfo.getMcEndDate());
            return CommonConstant.ONE;
        }
        //查询营销活动商户信息表，当前商户的活动是否存在营销活动信息表中，或所属商圈在营销活动信息表中，如果存在，则无需登记营销活动商户信息表
        List<TMMcMchntInfo> tmMcMchntInfoList = matchMcMchntInfoByUsingMchntInfoAndMcNo(globalInstId, mchntNo, mcMchntFeeDiscountTransData.getMchntArea(), mcMchntFeeDiscountTransData.getMcNo());
        if (null == tmMcMchntInfoList || tmMcMchntInfoList.isEmpty()) {
            //为新增商户添加营销活动商户信息表数据
            GenerateTableDataService generateTableDataService = new GenerateTableDataService();
            boolean generateTmMcMchntInfoResult = generateTableDataService.generateTmMcMchntInfoData(mcMchntFeeDiscountTransData, rglog);
            if (!generateTmMcMchntInfoResult) {
                rglog.info("法人机构<{}> 商户<{}> 营销活动<{}> 登记营销活动商户信息表数据失败!", globalInstId, mchntNo, tmStatMfdCriteria.getMcNo());
                return CommonConstant.ONE;
            }

            boolean generateTmPlatBizTmpMcMchntInfoResult = generateTableDataService.generateTmPlatBizTmpMcMchntInfoData(mcMchntFeeDiscountTransData, rglog);
            if (!generateTmPlatBizTmpMcMchntInfoResult) {
                rglog.info("法人机构<{}> 商户<{}> 营销活动<{}> 登记临时表营销活动商户信息数据失败!", globalInstId, mchntNo, tmStatMfdCriteria.getMcNo());
                return CommonConstant.ONE;
            }
        } else {
            rglog.info("使用商户号 <{}>,商圈 <{}>,营销活动编号<{}> 查询到营销活动商户信息表信息，无需再次登记营销活动商户信息表数据!", mchntNo, mcMchntFeeDiscountTransData.getMchntArea(), mcMchntFeeDiscountTransData.getMcNo());
        }

        //设置营销活动编号
        mcMchntFeeDiscountTransData.setMcNo(tmMcMchntFeeDiscountInfo.getMcNo());
        //存量商户支持类型
        mcMchntFeeDiscountTransData.setStockMchntType(tmMcMchntFeeDiscountInfo.getStockMchntType());
        //设置优惠退出标识
        mcMchntFeeDiscountTransData.setTerminationFlag(tmMcMchntFeeDiscountInfo.getTerminationFlag());
        //设置统计周期
        mcMchntFeeDiscountTransData.setStatPeriod(tmMcMchntFeeDiscountInfo.getStatPeriod());
        //设置统计周期
        mcMchntFeeDiscountTransData.setMcStartDate(tmMcMchntFeeDiscountInfo.getMcStartDate());
        //设置统计周期
        mcMchntFeeDiscountTransData.setMcEndDate(tmMcMchntFeeDiscountInfo.getMcEndDate());
        //单个商户优惠笔数上限
        mcMchntFeeDiscountTransData.setQuantityLimit(tmMcMchntFeeDiscountInfo.getQuantityLimit());
        //单个商户优惠交易金额上限amount_limit
        mcMchntFeeDiscountTransData.setAmountLimit(tmMcMchntFeeDiscountInfo.getAmountLimit());
        //单个商户手续费优惠额上限fee_limit
        mcMchntFeeDiscountTransData.setFeeLimit(tmMcMchntFeeDiscountInfo.getFeeLimit());
        //达标后手续费优惠规则
        String afterFlag = tmMcMchntFeeDiscountInfo.getAfterFlag();
        String mchntFeeDisCountInfo;
        if (CommonConstant.ZERO_COMMON_CONSTANT.equals(afterFlag)) {
            mchntFeeDisCountInfo = CommonConstant.ONE_COMMON_CONSTANT;
        } else {
            mchntFeeDisCountInfo = CommonConstant.ZERO_COMMON_CONSTANT;
        }
        mcMchntFeeDiscountTransData.setMchntFeeDiscountMethod(mchntFeeDisCountInfo);
        //新增商户优惠交易金额上限
        mcMchntFeeDiscountTransData.setNewMchntAmountLimit(tmMcMchntFeeDiscountInfo.getNewMchntAmountLimit());
        //活动期间新增商户营销活动规则号设置为0
        mcMchntFeeDiscountTransData.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
        //设置活动预算资金
        mcMchntFeeDiscountTransData.setBudget(tmMcMchntFeeDiscountInfo.getBudget());
        //活动状态
        mcMchntFeeDiscountTransData.setMcStatus(tmMcMchntFeeDiscountInfo.getMcStatus());
        //新增商户免费额度类型
        mcMchntFeeDiscountTransData.setNewmrctFreeLmtTyp(tmMcMchntFeeDiscountInfo.getNewmrctFreeLmtTyp());

        return CommonConstant.ZERO;
    }

    /**
     * 获取商户手续费优惠规则,并获取规则计算优惠上限
     *
     * @return CommonConstant.ZERO:成功，流程继续  1:本次结束，继续下一次
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/7/18
     */
    private int getCalRuleNoAndFeeDiscountLimit(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {

        String instId = mcMchntFeeDiscountTransData.getInstId();
        String mcNo = mcMchntFeeDiscountTransData.getMcNo();
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();

        /* 获取营销活动规则信息 */
        rglog.debug("获取营销活动优惠规则信息 CRITERIA_VALUE=<{}>", mcMchntFeeDiscountTransData.getCriteriaValue());
        List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList = getMchntFeeDiscountMcRuleInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountRuleInfoList || tmMcMchntFeeDiscountRuleInfoList.isEmpty()) {
            /* 未取到营销活动规则信息,本营销活动不可以优惠! */
            rglog.info("获取机构<{}>的营销活动<{}>优惠规则信息匹配失败,本营销活动不予优惠!", instId, mcNo);
            return CommonConstant.ONE;
        }

        /* 代码判断匹配到了哪条规则上 */
        TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo;
        //存量商户当前统计值
        BigDecimal criteriaValue = new BigDecimal(mcMchntFeeDiscountTransData.getCriteriaValue()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList1 = new ArrayList<>();
        for (TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo1 : tmMcMchntFeeDiscountRuleInfoList) {
            /** 控制下限 */
            BigDecimal floor = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaFloor()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            /** 控制上限 */
            BigDecimal celling = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaCelling()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            /* 按照左包右不包原则判断 */
            if (CommonConstant.ZERO <= criteriaValue.compareTo(floor) && CommonConstant.ZERO > criteriaValue.compareTo(celling)) {
                tmMcMchntFeeDiscountRuleInfoList1.add(tmMcMchntFeeDiscountRuleInfo1);
            }
        }
        if (tmMcMchntFeeDiscountRuleInfoList1.isEmpty()) {
            rglog.info("获取机构<{}>的营销活动<{}>优惠规则信息匹配失败,无满足条件的规则,本营销活动不予优惠!", instId, mcNo);
            return CommonConstant.ONE;
        } else {
            if (CommonConstant.ONE != tmMcMchntFeeDiscountRuleInfoList1.size()) {
                /* 超过1条以上规则符合条件 */
                tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList1.stream().max(Comparator.comparing(TMMcMchntFeeDiscountRuleInfo::getRuleIndex)).get();
            } else {
                tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList1.get(CommonConstant.ZERO);
            }
        }

        //商户手续费减免类营销活动规则信息转存到mcMchntFeeDiscountTransData
        copyTMMcMfdRuleInfo(mcMchntFeeDiscountTransData, tmMcMchntFeeDiscountRuleInfo);

        if (null != mcMchntFeeDiscountTransData.getMrctDisUpLmtVal() && !"".equals(mcMchntFeeDiscountTransData.getMrctDisUpLmtVal())) {
            rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, mcMchntFeeDiscountTransData.getMrctDisUpLmtVal());
            mcMchntFeeDiscountTransData.setDiscountLimit(mcMchntFeeDiscountTransData.getMrctDisUpLmtVal());
        } else {
            /* 根据营销活动规则计算商户当前优惠限额 */
            if (FeeCalTypeEnum.TYPE_0.getRuleType().equals(tmMcMchntFeeDiscountRuleInfo.getCalRuleNo())) {
                /* 无需取优惠限额的计算规则,直接使用最大值 */
                mcMchntFeeDiscountTransData.setDiscountLimit(CommonConstant.BIG_NUMBER);

            } else if (FeeCalTypeEnum.TYPE_1.getRuleType().equals(tmMcMchntFeeDiscountRuleInfo.getCalRuleNo()) ||
                    FeeCalTypeEnum.TYPE_13.getRuleType().equals(tmMcMchntFeeDiscountRuleInfo.getCalRuleNo())) {
                /* 无需取优惠限额的计算规则,直接使用规则中的限额 */
                mcMchntFeeDiscountTransData.setDiscountLimit(tmMcMchntFeeDiscountRuleInfo.getDiscountLimit());

            } else {

                TMPlatCalRule tmPlatCalRule = selectCalculationRuleInfoByPK(instId, tmMcMchntFeeDiscountRuleInfo.getCalRuleNo());
                if (null == tmPlatCalRule) {
                    /* 未取到营销活动规则信息,本营销活动不可以优惠! */
                    rglog.info("获取机构<{}>的营销活动<{}>的优惠规则<{}>的计算规则<{}>信息失败,本营销活动不予优惠!",
                            instId, mcNo, tmMcMchntFeeDiscountRuleInfo.getRuleIndex(), tmMcMchntFeeDiscountRuleInfo.getCalRuleNo());
                    return CommonConstant.ONE;
                }
                //手续费计算上限规则信息转存
                convertMchntFeeDiscountMcCalRuleInfo(tmPlatCalRule, mcMchntFeeDiscountTransData);

                //根据计算规则计算当前商户手续费优惠限额
                String month = DateUtil.getFutureMonDay(CommonConstant.MINUS_ONE).substring(0, 6);
                rglog.debug("机构 INST_ID=<{}>, 商户号 MCHNT_NO=<{}>, 月份 MONTH=<{}>", instId, mchntNo, month);

                //商户上月日均余额直接取达标统计表中的当前统计值
                String mchntDeposit = mcMchntFeeDiscountTransData.getCriteriaValue();

                BigDecimal TWO = new BigDecimal("2");
                BigDecimal HUNDARD_1 = new BigDecimal("125");
                BigDecimal HUNDARD_5 = new BigDecimal("500");
                BigDecimal THOUSAND_30 = new BigDecimal("30000");
                BigDecimal THOUSAND_50 = new BigDecimal("50000");
                BigDecimal THOUSAND_100 = new BigDecimal("100000");
                //商户日均存款
                BigDecimal deposit = new BigDecimal(mchntDeposit).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal tenThousand = new BigDecimal("10000").setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                BigDecimal discountLimit;

                //手续费计算规则类型
                String ruleType = mcMchntFeeDiscountTransData.getRuleType();

                if (null != ruleType) {
                    switch (FeeCalTypeEnum.getByValue(ruleType)) {
                        case TYPE_0:
                            /* 无上限 */
                            rglog.info("手续费计算规则类型 <{}> 无上限", ruleType);
                            discountLimit = new BigDecimal(CommonConstant.BIG_NUMBER);
                            break;
                        case TYPE_1:
                            /* 指定具体数值 */
                            rglog.info("手续费计算规则类型 <{}> 指定具体数值", ruleType);
                            discountLimit = new BigDecimal(mcMchntFeeDiscountTransData.getDiscountLimit());
                            break;
                        case TYPE_2:
                            /* 上月日均存款万位取整+3万 */
                            rglog.info("手续费计算规则类型 <{}> 上月日均存款万位取整+3万", ruleType);
                            discountLimit = deposit.divideToIntegralValue(tenThousand).add(THOUSAND_30);
                            break;
                        case TYPE_3:
                            /* 上月日均存款*2+3万 */
                            rglog.info("手续费计算规则类型 <{}> 上月日均存款*2+3万", ruleType);
                            discountLimit = deposit.multiply(TWO).add(THOUSAND_30);
                            break;
                        case TYPE_4:
                            /* 上月日均存款万位取整+5万 */
                            rglog.info("手续费计算规则类型 <{}> 上月日均存款万位取整+5万", ruleType);
                            discountLimit = deposit.divideToIntegralValue(tenThousand).add(THOUSAND_50);
                            break;
                        case TYPE_5:
                            /* 上月日均存款*2+5万 */
                            rglog.info("手续费计算规则类型 <{}> 上月日均存款*2+5万", ruleType);
                            discountLimit = deposit.multiply(TWO).add(THOUSAND_50);
                            break;
                        case TYPE_6:
                            /* 上月日均存款每10万优惠125元 */
                            rglog.info("手续费计算规则类型 <{}> 上月日均存款每10万优惠125元", ruleType);
                            discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_1);
                            break;
                        case TYPE_7:
                            /* 上月日均存款每10万优惠500元 */
                            rglog.info("手续费计算规则类型 <{}> 上月日均存款每10万优惠500元", ruleType);
                            discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_5);
                            break;
                        case TYPE_8:
                            /* 上月日均存款 */
                            rglog.info("手续费计算规则类型 <{}> 上月日均存款值", ruleType);
                            discountLimit = deposit;
                            break;
                        case TYPE_9:
                            /* 上月日均存款每万元取整*2+3万 */
                            rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+3万", ruleType);
                            discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_30);
                            break;
                        case TYPE_10:
                            /* 上月日均存款每万元*2+5万 */
                            rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+5万", ruleType);
                            discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_50);
                            break;
                        case TYPE_11:
                            /* 上月日均存款每十万元*2+3万 */
                            rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+3万", ruleType);
                            discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_30);
                            break;
                        case TYPE_12:
                            /* 上月日均存款每十万元*2+5万 */
                            rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+5万", ruleType);
                            discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_50);
                            break;
                        default:
                            rglog.error("不支持的计算规则类型 <{}>", ruleType);
                            return CommonConstant.ONE;
                    }
                    rglog.info("计算出的规则额度限制 DISCOUNT_LIMIT=<{}>", discountLimit.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
                    mcMchntFeeDiscountTransData.setDiscountLimit(discountLimit.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
                } else {
                    mcMchntFeeDiscountTransData.setDiscountLimit(CommonConstant.ZERO_AMOUNT);
                }
            }
        }

        rglog.info("商户<{}>的商户手续费优惠营销活动<{}>的规则<{}>优惠限额为<{}>", mchntNo, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getDiscountLimit());
        return CommonConstant.ZERO;
    }


    /**
     * 存量商户根据
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntFeeDiscountRuleInfo 商户手续费减免类营销活动规则信息表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/4/20 18:01
     */
    private List<TMMcMchntFeeDiscountRuleInfo> getMchntFeeDiscountMcRuleInfo(String instId, String mcNo) throws Exception {

        McRuleInfoMapper mcRuleInfoMapper = new McRuleInfoMapperImpl();
        return mcRuleInfoMapper.selectMchntFeeDiscountRuleInfoList(instId, mcNo);
    }

    /**
     * 获取商户手续费营销活动的活动规则对应的计算规则
     *
     * @param instId 法人机构号
     * @param ruleNo 规则编号
     * @return cc.rengu.igas.momp.common.entity.TMPlatCalRule 计算规则码表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/4/20 21:01
     */
    private TMPlatCalRule selectCalculationRuleInfoByPK(String instId, String ruleNo) throws Exception {

        TMPlatCalRuleMapper tmPlatCalRuleMapper = new TMPlatCalRuleMapperImpl();
        return tmPlatCalRuleMapper.selectCalculationRuleInfoByPrimaryKey(instId, ruleNo);
    }

    /**
     * 商户手续费优惠营销活动计算规则信息转换
     *
     * @param tmPlatCalRule               计算规则码表
     * @param mcMchntFeeDiscountTransData 流程中使用的实体对象
     * @author liujinan
     * @since 2020/4/20 21:06
     */
    private void convertMchntFeeDiscountMcCalRuleInfo(TMPlatCalRule tmPlatCalRule, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 规则编号 */
        mcMchntFeeDiscountTransData.setRuleNo(tmPlatCalRule.getRuleNo());
        /* 业务类型 */
        mcMchntFeeDiscountTransData.setBizType(tmPlatCalRule.getBizType());
        /* 规则类型 */
        mcMchntFeeDiscountTransData.setRuleType(tmPlatCalRule.getRuleType());
        /* 规则描述 */
        mcMchntFeeDiscountTransData.setRuleContent(tmPlatCalRule.getRuleContent());
        /* 处理服务类名 */
        mcMchntFeeDiscountTransData.setServiceName(tmPlatCalRule.getServiceName());
        /* 规则启用状态 */
        mcMchntFeeDiscountTransData.setRuleStatus(tmPlatCalRule.getRuleStatus());
    }

    /**
     * 计算优惠的手续费
     *
     * @return CommonConstant.ZERO:成功，流程继续  1:本次结束，继续下一次
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/4/30
     */
    private int getFeeDiscount(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail) throws Exception {

        //根据营销活动规则计算补贴减免金额
        String subsidy = calculateMchntFeeDiscountSubsidy(mcMchntFeeDiscountTransData, feeOrderDetail);

        if (null == subsidy) {
            rglog.info("按规则计算机构<{}>的营销活动<{}>手续费优惠金额异常!", globalInstId, mcMchntFeeDiscountTransData.getMcNo());
            return CommonConstant.ONE;
        } else {
            BigDecimal zeroAmt = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal totalSubsidy = new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeDiscount()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            if (CommonConstant.ZERO == zeroAmt.compareTo(totalSubsidy)) {
                /* 优惠金额为0,不优惠商户手续费 */
                rglog.info("通过计算商户优惠手续费为0,不优惠!");
                return CommonConstant.ONE;
            } else {
                rglog.info("初步计算出的机构<{}>的商户的<{}>的商户手续费优惠营销活动<{}>的减免金额<{}>,实收手续费<{}>", globalInstId, mcMchntFeeDiscountTransData.getMchntNo(),
                        mcMchntFeeDiscountTransData.getMcNo(), mcMchntFeeDiscountTransData.getMchntFeeDiscount(), mcMchntFeeDiscountTransData.getMchntFeeActual());
            }
        }

        /* 获取交易额度上限 */
        rglog.info("机构<{}> 商户<{}> 营销活动<{}> 获取各维度统计数据开始...!", globalInstId, mcMchntFeeDiscountTransData.getMchntNo(), mcMchntFeeDiscountTransData.getMcNo());
        int returnCode = fetchAllMchntFeeDiscountMcQuotaData(mcMchntFeeDiscountTransData);
        if (CommonConstant.ONE == returnCode) {
            rglog.info("获取机构<{}>的营销活动<{}>各维度限额和额度未通过,本营销活动不予优惠!", globalInstId, mcMchntFeeDiscountTransData.getMcNo());
            return CommonConstant.ONE;
        }

        /* 判断交易额度上限 */
        rglog.info("机构<{}> 商户<{}> 营销活动<{}> 判断交易额度限制开始...!", globalInstId, mcMchntFeeDiscountTransData.getMchntNo(), mcMchntFeeDiscountTransData.getMcNo());
        returnCode = checkMchntFeeDiscountLimits(mcMchntFeeDiscountTransData, feeOrderDetail);
        if (CommonConstant.ONE == returnCode) {
            rglog.info("机构<{}>的营销活动<{}>判断各维度限额和额度未通过,本营销活动不予优惠!", globalInstId, mcMchntFeeDiscountTransData.getMcNo());
            return CommonConstant.ONE;
        }
        //设置实收手续费金额
        feeOrderDetail.setMchntFeeActual(mcMchntFeeDiscountTransData.getMchntFeeActual());
        //设置手续费优惠金额
        feeOrderDetail.setMchntFeeDiscount(mcMchntFeeDiscountTransData.getMchntFeeDiscount());

        rglog.info("通过限额检查后计算出的机构<{}>的商户的<{}>的商户手续费优惠营销活动<{}>的减免金额<{}>,实收手续费<{}>", globalInstId, mcMchntFeeDiscountTransData.getMchntNo(),
                mcMchntFeeDiscountTransData.getMcNo(), mcMchntFeeDiscountTransData.getMchntFeeDiscount(), mcMchntFeeDiscountTransData.getMchntFeeActual());

        BigDecimal totalSubsidy = new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeDiscount()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //本笔手续费订单金额(接口上送的金额)
        BigDecimal mchntSettleAmt = new BigDecimal(feeOrderDetail.getMchntSettleAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //本笔手续费优惠订单金额
        BigDecimal mchntFeeDiscountTransAmt = new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeDiscountTransAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        if (CommonConstant.ZERO == BigDecimal.ZERO.compareTo(totalSubsidy) && CommonConstant.ZERO == mchntSettleAmt.compareTo(mchntFeeDiscountTransAmt)) {
            /* 优惠金额为0,不优惠商户手续费 */
            rglog.info("最终通过计算出的商户优惠手续费为0,不优惠!!!");
            return CommonConstant.ONE;
        }

        return CommonConstant.ZERO;
    }


    /**
     * 商户基本信息转存
     *
     * @throws Exception 异常信息
     * @author liujinan
     */
    private void copyMchntBaseInfo(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TBMchntBaseInfo mchntBaseInfo) {
        // 机构编码
        mcMchntFeeDiscountTransData.setInstId(mchntBaseInfo.getInstId());
        // 商户类型
        mcMchntFeeDiscountTransData.setMchntType(mchntBaseInfo.getMchntType());
        // 商户名称
        mcMchntFeeDiscountTransData.setMchntName(mchntBaseInfo.getMchntName());
        // 签约机构
        mcMchntFeeDiscountTransData.setSignInstId(mchntBaseInfo.getSignInstId());
        // 商户等级
        mcMchntFeeDiscountTransData.setMchntLevel(mchntBaseInfo.getMchntLevel());
        // 所属商圈
        mcMchntFeeDiscountTransData.setMchntArea(mchntBaseInfo.getMchntArea());
        // 所属平台商户
        mcMchntFeeDiscountTransData.setPlatMchntNo(mchntBaseInfo.getPlatMchntNo());
        // 商户入驻时间
        mcMchntFeeDiscountTransData.setMchntExpandTime(mchntBaseInfo.getMchntExpandTime());
        // 企业性质
        mcMchntFeeDiscountTransData.setMchntNature(mchntBaseInfo.getMchntNature());
        // 商户号
        mcMchntFeeDiscountTransData.setMchntNo(mchntBaseInfo.getMchntNo());
        // 商户入驻时间
        mcMchntFeeDiscountTransData.setMchntExpandTime(mchntBaseInfo.getMchntExpandTime());
    }

    /**
     * 商户手续费减免类营销活动规则信息转存
     *
     * @throws Exception 异常信息
     * @author liujinan
     */
    private void copyTMMcMfdRuleInfo(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo) {
        // 顺序号
        mcMchntFeeDiscountTransData.setRuleIndex(tmMcMchntFeeDiscountRuleInfo.getRuleIndex());
        // 控制下限
        mcMchntFeeDiscountTransData.setCriteriaFloor(tmMcMchntFeeDiscountRuleInfo.getCriteriaFloor());
        // 控制上限
        mcMchntFeeDiscountTransData.setCriteriaCelling(tmMcMchntFeeDiscountRuleInfo.getCriteriaCelling());
        // 优惠周期
        mcMchntFeeDiscountTransData.setDiscountPeriod(tmMcMchntFeeDiscountRuleInfo.getDiscountPeriod());
        // 优惠类型
        mcMchntFeeDiscountTransData.setDiscountType(tmMcMchntFeeDiscountRuleInfo.getDiscountType());
        // 优惠力度
        mcMchntFeeDiscountTransData.setDiscount(tmMcMchntFeeDiscountRuleInfo.getDiscount());
        // 计算规则编号
        mcMchntFeeDiscountTransData.setCalRuleNo(tmMcMchntFeeDiscountRuleInfo.getCalRuleNo());
        //优惠上限
        mcMchntFeeDiscountTransData.setDiscountLimit(tmMcMchntFeeDiscountRuleInfo.getDiscountLimit());
    }

    /**
     * 商户手续费减免类营销活动信息转存
     *
     * @throws Exception 异常信息
     * @author liujinan
     */
    private void copyTMMcMfdInfo(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo) {
        //设置营销活动编号
        mcMchntFeeDiscountTransData.setMcNo(tmMcMchntFeeDiscountInfo.getMcNo());
        //设置商户手续费收取类型
        if ("1".equals(mcMchntFeeDiscountTransData.getNewMchntFlag())) {
            //手续费减免达标数据统计表中如果是新增商户，则商户是营销活动期间入住的，只要查出来记录，说明现在还在新商户免手续费期间
            mcMchntFeeDiscountTransData.setNewMchntFeeFlag("1");
        } else {
            //如果查到的是存量商户，则应该是存量的商户，按照规则计算手续费的情况
            mcMchntFeeDiscountTransData.setNewMchntFeeFlag("0");
        }
        //存量商户支持类型
        mcMchntFeeDiscountTransData.setStockMchntType(tmMcMchntFeeDiscountInfo.getStockMchntType());
        //设置优惠退出标识
        mcMchntFeeDiscountTransData.setTerminationFlag(tmMcMchntFeeDiscountInfo.getTerminationFlag());
        //设置统计周期
        mcMchntFeeDiscountTransData.setStatPeriod(tmMcMchntFeeDiscountInfo.getStatPeriod());
        //设置统计周期
        mcMchntFeeDiscountTransData.setMcStartDate(tmMcMchntFeeDiscountInfo.getMcStartDate());
        //设置统计周期
        mcMchntFeeDiscountTransData.setMcEndDate(tmMcMchntFeeDiscountInfo.getMcEndDate());
        //单个商户优惠笔数上限
        mcMchntFeeDiscountTransData.setQuantityLimit(tmMcMchntFeeDiscountInfo.getQuantityLimit());
        //单个商户优惠交易金额上限amount_limit
        mcMchntFeeDiscountTransData.setAmountLimit(tmMcMchntFeeDiscountInfo.getAmountLimit());
        //单个商户手续费优惠额上限fee_limit
        mcMchntFeeDiscountTransData.setFeeLimit(tmMcMchntFeeDiscountInfo.getFeeLimit());
        //活动预算
        mcMchntFeeDiscountTransData.setBudget(tmMcMchntFeeDiscountInfo.getBudget());
        //达标后手续费优惠规则
        String afterFlag = tmMcMchntFeeDiscountInfo.getAfterFlag();
        String mchntFeeDisCountInfo;
        if (CommonConstant.ZERO_COMMON_CONSTANT.equals(afterFlag)) {
            mchntFeeDisCountInfo = CommonConstant.ONE_COMMON_CONSTANT;
        } else {
            mchntFeeDisCountInfo = CommonConstant.ZERO_COMMON_CONSTANT;
        }
        mcMchntFeeDiscountTransData.setMchntFeeDiscountMethod(mchntFeeDisCountInfo);
        //新增商户优惠交易金额上限
        mcMchntFeeDiscountTransData.setNewMchntAmountLimit(tmMcMchntFeeDiscountInfo.getNewMchntAmountLimit());
        // 营销活动状态
        mcMchntFeeDiscountTransData.setMcStatus(tmMcMchntFeeDiscountInfo.getMcStatus());
        // 新增商户免费额度类型
        mcMchntFeeDiscountTransData.setNewmrctFreeLmtTyp(tmMcMchntFeeDiscountInfo.getNewmrctFreeLmtTyp());
    }

    /**
     * 使用主键查询手续费减免活动周期统计表单条数据
     *
     * @param instId
     * @param mcNo
     * @param ruleIndex
     * @param periodStartDate
     * @param periodEndDate
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdPeriod
     * @throws Exception
     * @author liujinan
     * @date 2020/4/29
     */
    private TMStatMfdPeriod selectMchntFeeDiscountPeriodStatisticsByPK(String instId, String mcNo, String ruleIndex, String periodStartDate, String periodEndDate) throws Exception {

        TMStatMfdPeriodMapper tmStatMfdPeriodMapper = new TMStatMfdPeriodMapperImpl();
        return tmStatMfdPeriodMapper.selectMchntFeeDiscountPeriodStatisticsByPK(instId, mcNo, ruleIndex, periodStartDate, periodEndDate);
    }

    /**
     * 使用主键取手续费减免活动单日统计表单条数据
     *
     * @param instId
     * @param mcNo
     * @param ruleIndex
     * @param transDate
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdDay
     * @throws Exception
     * @author liujinan
     * @date 2020/4/29
     */
    private TMStatMfdDay selectMchntFeeDiscountDayStatisticsByPK(String instId, String mcNo, String ruleIndex, String transDate) throws Exception {

        TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
        return tmStatMfdDayMapper.selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, transDate);
    }

    /**
     * 使用主键取手续费减免活动商户统计表单条数据
     *
     * @param instId
     * @param mcNo
     * @param ruleIndex
     * @param mchntNo
     * @param periodStartDate
     * @param periodEndDate
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt
     * @throws Exception
     * @author liujinan
     * @date 2020/4/29
     */
    private TMStatMfdMchnt selectMchntFeeDiscountMchntStatisticsByPK(String instId, String mcNo, String ruleIndex, String mchntNo, String periodStartDate, String periodEndDate) throws Exception {

        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
    }

    /**
     * 登记单条订单明细表
     *
     * @param comboMchntFeeDiscountRequest
     * @param feeOrderDetail
     * @param mcMchntFeeDiscountTransData
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/13
     */
    private void recordSingleTxnOrderDetail(ComboMchntFeeDiscountRequest comboMchntFeeDiscountRequest,
                                            PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        TMTxnOrderDet tmTxnOrderDet = new TMTxnOrderDet();
        // 机构编码
        tmTxnOrderDet.setInstId(comboMchntFeeDiscountRequest.getHeader().getInstId());
        // 交易日期
        tmTxnOrderDet.setTxnDate(comboMchntFeeDiscountRequest.getHeader().getTransDate());
        //前端流水号
        tmTxnOrderDet.setFrontSeqNum(comboMchntFeeDiscountRequest.getHeader().getTraceNo());
        //订单号
        tmTxnOrderDet.setOrderId(comboMchntFeeDiscountRequest.getMchntOrderId());
        //商户编号
        tmTxnOrderDet.setMchntNo(mcMchntFeeDiscountTransData.getMchntNo());
        //用户编号
        tmTxnOrderDet.setUserId(comboMchntFeeDiscountRequest.getUserId());
        //核对状态
        tmTxnOrderDet.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        //业务状态 00:业务处理成功
        tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        //营销活动类型 20:手续费减免活动
        tmTxnOrderDet.setMcType(McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode());
        //原始金额
        tmTxnOrderDet.setOriginalAmt(feeOrderDetail.getMchntFeeReceivable());
        //营销活动编号
        tmTxnOrderDet.setMcNo(mcMchntFeeDiscountTransData.getMcNo());

        //新商户免手续费不用获取规则,赋值为0
        String ruleIndex = mcMchntFeeDiscountTransData.getRuleIndex();
        if (null == ruleIndex) {
            ruleIndex = "0";
        }
        //规则顺序号
        tmTxnOrderDet.setRuleIndex(ruleIndex);
        //总补贴金额
        tmTxnOrderDet.setSubsidy(feeOrderDetail.getMchntFeeDiscount());
        //机构补贴金额
        tmTxnOrderDet.setBankSubsidy(feeOrderDetail.getMchntFeeDiscount());
        //商户补贴金额
        tmTxnOrderDet.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);
        JSONObject relativeDataJson = new JSONObject();
        //订单金额
        relativeDataJson.put("orderAmt", feeOrderDetail.getMchntSettleAmt());
        //商户清算金额
//        relativeDataJson.put("mchntSettleAmt",feeOrderDetail.getMchntSettleAmt());
        //手续费收取方式
        relativeDataJson.put("feeInputMode", feeOrderDetail.getFeeInputMode());
        //商户手续费优惠类型
        relativeDataJson.put("discountType", mcMchntFeeDiscountTransData.getDiscountType());
        //优惠力度
        relativeDataJson.put("discount", mcMchntFeeDiscountTransData.getDiscount());
        //商户应收手续费
        relativeDataJson.put("mchntFeeReceivable", feeOrderDetail.getMchntFeeReceivable());
        //商户应收手续费费率
        relativeDataJson.put("mchntFeeReceivableRate", feeOrderDetail.getMchntFeeReceivableRate());
        //商户手续费营销活动编号
//        relativeDataJson.put("mchntFeeDiscountMcNo",mcMchntFeeDiscountTransData.getMcNo());
        //手续费优惠金额
//        relativeDataJson.put("mchntFeeDiscount",feeOrderDetail.getMchntFeeDiscount());
        //实收手续费金额
//        relativeDataJson.put("mchntFeeActual",feeOrderDetail.getMchntFeeActual());

        String relativeData = relativeDataJson.toString();
        //关联信息
        tmTxnOrderDet.setRelativeData(relativeData);
        //订单预留信息
        tmTxnOrderDet.setOrderRemark(relativeData);
        //订单预留信息
        tmTxnOrderDet.setOrderRemark(feeOrderDetail.getMchntFeeReceivable());
        //创建人
        tmTxnOrderDet.setOprId(CommonConstant.DEFAULT_OPR_ID);
        //创建时间
        tmTxnOrderDet.setCreateTime(newTimeStamp);
        //最后修改人
        tmTxnOrderDet.setLastOprId("");
        //修改时间
        tmTxnOrderDet.setUpdateTime("");
        // 备用字段1
        tmTxnOrderDet.setRemark1("");
        // 备用字段2
        tmTxnOrderDet.setRemark2("");
        // 备用字段3
        tmTxnOrderDet.setRemark3("");
        // 备用字段4
        tmTxnOrderDet.setRemark4("");
        // 备用字段5
        tmTxnOrderDet.setRemark5("");

        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        int returnCodeTmTxnOrderDet = tmTxnOrderDetMapper.insertSingleRecordIntoTMTxnOrderDet(tmTxnOrderDet);
        if (Database.DBS_SUCCESS != returnCodeTmTxnOrderDet) {
            rglog.error("插入订单明细数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}, MC_NO=<{}>",
                    tmTxnOrderDet.getInstId(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId(), tmTxnOrderDet.getMchntNo(), tmTxnOrderDet.getMcNo());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }
    }

    /**
     * 生成单条订单明细数据
     *
     * @param comboMchntFeeDiscountRequest
     * @param feeOrderDetail
     * @param mcMchntFeeDiscountTransData
     * @return TMTxnOrderDet
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/7/21
     */
    private TMTxnOrderDet generateSingleTxnOrderDetail(ComboMchntFeeDiscountRequest comboMchntFeeDiscountRequest,
                                                       PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {

        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        TMTxnOrderDet tmTxnOrderDet = new TMTxnOrderDet();
        // 机构编码
        tmTxnOrderDet.setInstId(comboMchntFeeDiscountRequest.getHeader().getInstId());
        // 交易日期
        tmTxnOrderDet.setTxnDate(comboMchntFeeDiscountRequest.getHeader().getTransDate());
        //前端流水号
        tmTxnOrderDet.setFrontSeqNum(comboMchntFeeDiscountRequest.getHeader().getTraceNo());
        //订单号
        tmTxnOrderDet.setOrderId(comboMchntFeeDiscountRequest.getMchntOrderId());
        //商户编号
        tmTxnOrderDet.setMchntNo(feeOrderDetail.getMchntNo());
        //用户编号
        tmTxnOrderDet.setUserId(comboMchntFeeDiscountRequest.getUserId());
        //核对状态
        tmTxnOrderDet.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        //业务状态 00:业务处理成功
        tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        //营销活动类型 20:手续费减免活动
        tmTxnOrderDet.setMcType(McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode());
        //原始金额,具体是哪个值
        tmTxnOrderDet.setOriginalAmt(feeOrderDetail.getMchntFeeReceivable());
        //营销活动编号
        tmTxnOrderDet.setMcNo(mcMchntFeeDiscountTransData.getMcNo());

        //新商户免手续费不用获取规则,赋值为0
        String ruleIndex = mcMchntFeeDiscountTransData.getRuleIndex();
        if (null == ruleIndex) {
            ruleIndex = CommonConstant.ZERO_COMMON_CONSTANT;
        }
        //规则顺序号
        tmTxnOrderDet.setRuleIndex(ruleIndex);
        //总补贴金额
        tmTxnOrderDet.setSubsidy(feeOrderDetail.getMchntFeeDiscount());
        //机构补贴金额
        tmTxnOrderDet.setBankSubsidy(feeOrderDetail.getMchntFeeDiscount());
        //商户补贴金额
        tmTxnOrderDet.setMchntSubsidy(CommonConstant.ZERO_AMOUNT);
        JSONObject relativeDataJson = new JSONObject();
        //订单金额
        relativeDataJson.put("orderAmt", feeOrderDetail.getMchntSettleAmt());
        //手续费收取方式
        relativeDataJson.put("feeInputMode", feeOrderDetail.getFeeInputMode());
        //商户应收手续费
        relativeDataJson.put("mchntFeeReceivable", feeOrderDetail.getMchntFeeReceivable());
        //商户应收手续费费率
        relativeDataJson.put("mchntFeeReceivableRate", feeOrderDetail.getMchntFeeReceivableRate());
        //商户手续费优惠类型
        relativeDataJson.put("discountType", mcMchntFeeDiscountTransData.getDiscountType());
        //优惠力度
        relativeDataJson.put("discount", mcMchntFeeDiscountTransData.getDiscount());

        String relativeData = relativeDataJson.toString();
        //关联信息
        tmTxnOrderDet.setRelativeData(relativeData);
        //订单预留信息
        tmTxnOrderDet.setOrderRemark(relativeData);
        //创建人
        tmTxnOrderDet.setOprId(CommonConstant.DEFAULT_OPR_ID);
        //创建时间
        tmTxnOrderDet.setCreateTime(newTimeStamp);
        //最后修改人
        tmTxnOrderDet.setLastOprId("");
        //修改时间
        tmTxnOrderDet.setUpdateTime("");
        // 备用字段1
        tmTxnOrderDet.setRemark1("");
        // 备用字段2
        tmTxnOrderDet.setRemark2("");
        // 备用字段3
        tmTxnOrderDet.setRemark3("");
        // 备用字段4
        tmTxnOrderDet.setRemark4("");
        // 备用字段5
        tmTxnOrderDet.setRemark5("");
        //商户优惠交易金额
        tmTxnOrderDet.setDisTxAmt(mcMchntFeeDiscountTransData.getMchntFeeDiscountTransAmt());

        return tmTxnOrderDet;
    }

    /**
     * 登记多条订单明细数据
     *
     * @param tmTxnOrderDetList
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/7/21
     */
    private void recordTxnOrderDetail(List<TMTxnOrderDet> tmTxnOrderDetList) throws Exception {

        int returnCodeTmTxnOrderDet;

        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        //循环登记订单明细数据
        for (TMTxnOrderDet tmTxnOrderDet : tmTxnOrderDetList) {
            returnCodeTmTxnOrderDet = tmTxnOrderDetMapper.insertSingleRecordIntoTMTxnOrderDet(tmTxnOrderDet);
            if (Database.DBS_SUCCESS != returnCodeTmTxnOrderDet) {
                rglog.error("插入订单明细数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}, MC_NO=<{}>",
                        tmTxnOrderDet.getInstId(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getOrderId(), tmTxnOrderDet.getMchntNo(), tmTxnOrderDet.getMcNo());
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
        }
    }

    /**
     * 登记订单流水表
     *
     * @param comboMchntFeeDiscountRequest
     * @return void
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/13
     */
    private void recordTxnOrder(ComboMchntFeeDiscountRequest comboMchntFeeDiscountRequest, List<PaymentOrderMchntFeeDiscountInfoBean> returnFeeOrderDetailList) throws Exception {
        String newTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());

        TMTxnOrder tmTxnOrder = new TMTxnOrder();
        //机构编码
        tmTxnOrder.setInstId(comboMchntFeeDiscountRequest.getHeader().getInstId());
        //交易日期
        tmTxnOrder.setTxnDate(comboMchntFeeDiscountRequest.getHeader().getTransDate());
        //交易时间
        tmTxnOrder.setTxnTime(comboMchntFeeDiscountRequest.getHeader().getTransTime());
        //内部交易码
        tmTxnOrder.setTxnNum(comboMchntFeeDiscountRequest.getHeader().getTxnNum());
        //业务细分
        tmTxnOrder.setBizType(comboMchntFeeDiscountRequest.getHeader().getBizType());
        //业务产品代码
        tmTxnOrder.setBizProdCode(comboMchntFeeDiscountRequest.getBizProdCode());
        //源系统标识
        tmTxnOrder.setMsgSrcId(comboMchntFeeDiscountRequest.getHeader().getSrcSysId());
        //前端流水号
        tmTxnOrder.setFrontSeqNum(comboMchntFeeDiscountRequest.getHeader().getTraceNo());
        //订单号
        tmTxnOrder.setOrderId(comboMchntFeeDiscountRequest.getMchntOrderId());
        //用户编号
        tmTxnOrder.setUserId(comboMchntFeeDiscountRequest.getUserId());
        //商户号 不存储值
        tmTxnOrder.setMchntNo("");
        //订单金额
        tmTxnOrder.setOrderAmt(MompAmountUtil.getTwoDecimal(comboMchntFeeDiscountRequest.getTransAmt()));

        BigDecimal txnAmt = BigDecimal.ZERO;
        BigDecimal subsidyAmt = BigDecimal.ZERO;
        for (PaymentOrderMchntFeeDiscountInfoBean paymentOrderMchntFeeDiscountInfoBean : returnFeeOrderDetailList) {
            txnAmt = txnAmt.add(new BigDecimal(paymentOrderMchntFeeDiscountInfoBean.getMchntFeeActual()));
            subsidyAmt = subsidyAmt.add(new BigDecimal(paymentOrderMchntFeeDiscountInfoBean.getMchntFeeDiscount()));
        }
        //实际支付金额
        tmTxnOrder.setTxnAmt(MompAmountUtil.getTwoDecimal(txnAmt.toString()));
        //总补贴金额
        tmTxnOrder.setSubsidyAmt(MompAmountUtil.getTwoDecimal(subsidyAmt.toString()));
        //机构补贴金额
        tmTxnOrder.setBankSubsidyAmt(MompAmountUtil.getTwoDecimal(subsidyAmt.toString()));
        //商户补贴金额
        tmTxnOrder.setMchntSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        //交易状态 1:交易成功
        tmTxnOrder.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        //业务状态 01：业务处理成功
        tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        //批量对账状态 0：未对账
        tmTxnOrder.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        //订单预留信息  所有的订单的优惠手续费为0时，本笔订单流水登记有优惠但是不参与对账
        if (subsidyAmt.compareTo(BigDecimal.ZERO) == CommonConstant.ZERO) {
            tmTxnOrder.setOrderRemark(CommonConstant.DISCOUNT_FLAG_TRUE_CHECK_FLAG_FALSE);
        } else {
            tmTxnOrder.setOrderRemark(CommonConstant.DISCOUNT_FLAG_TRUE_CHECK_FLAG_TRUE);
        }
        //原交易日期
        tmTxnOrder.setOrigTxnDate("");
        //原交易流水号
        tmTxnOrder.setOrigSysSeqNum("");
        //原交易订单号
        tmTxnOrder.setOrigOrderId("");
        //创建人
        tmTxnOrder.setOprId(CommonConstant.DEFAULT_OPR_ID);
        //创建时间
        tmTxnOrder.setCreateTime(globalTimeStamp);
        //最后修改人
        tmTxnOrder.setLastOprId("");
        //修改时间
        tmTxnOrder.setUpdateTime("");
        // 备用字段1
        tmTxnOrder.setRemark1("");
        // 备用字段2
        tmTxnOrder.setRemark2("");
        // 备用字段3
        tmTxnOrder.setRemark3("");
        // 备用字段4
        tmTxnOrder.setRemark4("");
        // 备用字段5
        tmTxnOrder.setRemark5("");

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        int returnCodeTmTxnOrder = tmTxnOrderMapper.insertSingleRecordIntoTMTxnOrder(tmTxnOrder);
        if (Database.DBS_SUCCESS != returnCodeTmTxnOrder) {
            rglog.error("插入订单流水数据失败! INST_ID=<{}>, TRACE_NO=<{}>, ORDER_ID=<{}>, MCHNT_NO=<{}>",
                    tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId(), tmTxnOrder.getMchntNo());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }
    }

    /**
     * 手续费营销统计报表更新
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/5/13 10:34
     */
    private void updateFeeDiscountReport(ComboMchntFeeDiscountRequest comboMchntFeeDiscountRequest,
                                         McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail) throws Exception {
        String instId = comboMchntFeeDiscountRequest.getHeader().getInstId();
        String transDate = comboMchntFeeDiscountRequest.getHeader().getTransDate();
        String mcNo = mcMchntFeeDiscountTransData.getMcNo();
        String ruleIndex = mcMchntFeeDiscountTransData.getRuleIndex();
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();

        TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
        TMStatMfdDay tmStatMfdDay = new TMStatMfdDay();
        tmStatMfdDay.setInstId(instId);
        tmStatMfdDay.setMcNo(mcNo);
        tmStatMfdDay.setTxnDate(transDate);
        tmStatMfdDay.setRuleIndex(ruleIndex);
        tmStatMfdDay.setTotalQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
        tmStatMfdDay.setTotalAmtAcc(feeOrderDetail.getMchntFeeDiscount());
        tmStatMfdDay.setTxnQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
        tmStatMfdDay.setTxnAmtAcc(mcMchntFeeDiscountTransData.getMchntFeeDiscountTransAmt());
        tmStatMfdDay.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setMchntOldQualified(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setMchntNewQualified(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setMchntExitQty(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdDay.setAvgAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdDay.setPaidAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdDay.setCreateTime(globalTimeStamp);
        //更新时间
        tmStatMfdDay.setUpdateTime(globalTimeStamp);
        rglog.info("更新法人机构<{}> 营销活动<{}> 规则<{}>的营销活动单日统计数据（如更新不到数据则下一步进行插入）!", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
        int returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                rglog.info("插入法人机构<{}> 营销活动<{}> 规则<{}>的营销活动单日统计数据!", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay);
                if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                    /* 插入数据失败 */
                    rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            } else {
                /* 更新数据失败 */
                rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
        }
        //如果当规则不是0 ，则还需要更新规则为0的记录
        if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdDay.getRuleIndex())) {
            rglog.info("更新法人机构<{}> 营销活动<{}> 规则<{}>的营销活动单日统计数据（如更新不到数据则下一步进行插入）!", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
            tmStatMfdDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);

            returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                    rglog.info("插入法人机构<{}> 营销活动<{}> 规则<{}>的营销活动单日统计数据!", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                    int returnCode2 = tmStatMfdDayMapper.insertTMStatMfdDay(tmStatMfdDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }
        }

        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        TMStatMfdMchntDay tmStatMfdMchntDay = new TMStatMfdMchntDay();
        tmStatMfdMchntDay.setInstId(instId);
        tmStatMfdMchntDay.setMcNo(mcNo);
        tmStatMfdMchntDay.setTxnDate(transDate);
        tmStatMfdMchntDay.setMchntNo(mchntNo);
        tmStatMfdMchntDay.setRuleIndex(ruleIndex);
        tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
        tmStatMfdMchntDay.setTotalAmtAcc(feeOrderDetail.getMchntFeeDiscount());
        tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
        tmStatMfdMchntDay.setTxnAmtAcc(mcMchntFeeDiscountTransData.getMchntFeeDiscountTransAmt());
        tmStatMfdMchntDay.setTotalAvgAmt(CommonConstant.ZERO_AMOUNT);
        //优惠退出状态 0 正常优惠中
        tmStatMfdMchntDay.setExitStatus(CommonConstant.MC_NOT_EXIT_FLAG);
        //打款状态  0-未打款   //1-打款成功  //2-打款失败   //3-打款中
        tmStatMfdMchntDay.setCashbackStatus(CommonConstant.ZERO_COMMON_CONSTANT);
        tmStatMfdMchntDay.setCashbackAmt(CommonConstant.ZERO_AMOUNT);
        tmStatMfdMchntDay.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmStatMfdMchntDay.setCreateTime(globalTimeStamp);

        rglog.info("更新法人机构<{}> 营销活动<{}> 规则<{}>的手续费减免活动商户单日统计表数据（如更新不到数据则下一步进行插入）!", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
        returnCode = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                rglog.info("插入法人机构<{}> 营销活动<{}> 规则<{}>的手续费减免活动商户单日统计表数据!", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                    /* 插入数据失败 */
                    rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            } else {
                /* 更新数据失败 */
                rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
        }

        //如果当规则不是0 ，则还需要更新规则为0的记录
        if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdMchntDay.getRuleIndex())) {
            tmStatMfdMchntDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
            rglog.info("更新法人机构<{}> 营销活动<{}> 规则<{}>的手续费减免活动商户单日统计表数据（如更新不到数据则下一步进行插入）!", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());

            int returnCode2 = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
            if (CommonConstant.PROCESS_SUCCESS != returnCode2) {
                if (cc.rengu.utility.dbs.Database.DBS_NOT_FOUND == returnCode) {
                    rglog.info("插入法人机构<{}> 营销活动<{}> 规则<{}>的手续费减免活动商户单日统计表数据!", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                    int returnCode3 = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode3) {
                        /* 插入数据失败 */
                        rglog.error("插入法人机构<{}> 营销活动<{}> 规则<{}> 更新手续费减免活动商户单日统计表数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                        throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                    }
                } else {
                    /* 更新数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                    throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
                }
            }
        }
    }

    /**
     * 使用商户编号和当前交易日期获取商户当前统计周期内已参加的商户手续费优惠营销活动统计数据
     *
     * @param instId
     * @param mchntNo
     * @param transDate
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdCriteria
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/5
     */
    private TMStatMfdCriteria selectTMStatMfdCriteriaByUsingMchntNoAndDateRange(String instId, String mchntNo, String transDate) throws Exception {
        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        return tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndDateRange(instId, mchntNo, transDate);
    }

    /**
     * @param tmStatMfdCriteria
     * @param mcMchntFeeDiscountTransData
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/6
     */
    private void convertMchntFeeDiscountCriteria(TMStatMfdCriteria tmStatMfdCriteria, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {
        /** 营销活动编号 */
        mcMchntFeeDiscountTransData.setMcNo(tmStatMfdCriteria.getMcNo());
        /* 统计起始日期 */
        mcMchntFeeDiscountTransData.setPeriodStartDate(tmStatMfdCriteria.getPeriodStartDate());
        /* 统计结束日期 */
        mcMchntFeeDiscountTransData.setPeriodEndDate(tmStatMfdCriteria.getPeriodEndDate());
        /* 记录索引 */
        mcMchntFeeDiscountTransData.setRecIndex(tmStatMfdCriteria.getRecIndex());
        /** 商户新增标志 */
        mcMchntFeeDiscountTransData.setNewMchntFlag(tmStatMfdCriteria.getNewMchntFlag());

        /** 商户手续费类型 */
        if (CommonConstant.MCHNT_OLD_FLAG.equals(tmStatMfdCriteria.getNewMchntFlag())) {
            mcMchntFeeDiscountTransData.setNewMchntFeeFlag(CommonConstant.ZERO_COMMON_CONSTANT);
        } else {
            mcMchntFeeDiscountTransData.setNewMchntFeeFlag(CommonConstant.ONE_COMMON_CONSTANT);
        }

        /* 商户新增日期 */
        mcMchntFeeDiscountTransData.setNewMchntDate(tmStatMfdCriteria.getNewMchntDate());
        /* 新增商户有效起始日期 */
        mcMchntFeeDiscountTransData.setNewMchntStartDate(tmStatMfdCriteria.getNewMchntStartDate());
        /* 新增商户有效结束日期 */
        mcMchntFeeDiscountTransData.setNewMchntEndDate(tmStatMfdCriteria.getNewMchntEndDate());
        /* 优惠退出状态 */
        mcMchntFeeDiscountTransData.setExitDiscountStatus(tmStatMfdCriteria.getExitDiscountStatus());
        /* 存量商户支持类型 */
        mcMchntFeeDiscountTransData.setCriteriaType(tmStatMfdCriteria.getCriteriaType());
        /* 存量商户当前统计值 */
        mcMchntFeeDiscountTransData.setCriteriaValue(tmStatMfdCriteria.getCriteriaValue());
        /* 存量商户达标标志 */
        mcMchntFeeDiscountTransData.setCriteriaFlag(tmStatMfdCriteria.getCriteriaFlag());
        /* 存量商户达标日期 */
        mcMchntFeeDiscountTransData.setCriteriaDate(tmStatMfdCriteria.getCriteriaDate());
        /* 达标统计表数据创建时间 */
        mcMchntFeeDiscountTransData.setMfdCriteriaCreateTime(tmStatMfdCriteria.getCreateTime());
        /* 商户优惠上限值	 */
        mcMchntFeeDiscountTransData.setMrctDisUpLmtVal(tmStatMfdCriteria.getMrctDisUpLmtVal());
    }

    /**
     * 使用营销活动商户信息对象获取商户手续费优惠类营销活动基本信息
     *
     * @param instId
     * @param mcNo
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntFeeDiscountInfo
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/6/5
     */
    private TMMcMchntFeeDiscountInfo getMchntFeeDiscountMcInfo(String instId, String mcNo) throws Exception {
        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.selectMchntFeeDiscountMcDetailInfo(instId, mcNo);
    }

    /**
     * 请求报文检查
     *
     * @param comboMchntFeeDiscountRequest
     * @throws BizException 异常信息
     * @author liujinan
     * @date 2020/6/11
     */
    private void checkRequestMessage(ComboMchntFeeDiscountRequest comboMchntFeeDiscountRequest) throws BizException {
        // 检查上传字段 不能为负数
        /* 交易金额 */
        if (!StringUtil.isNullorEmpty(comboMchntFeeDiscountRequest.getTransAmt()) && new BigDecimal(comboMchntFeeDiscountRequest.getTransAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountRequest.getBizProdCode())) {
            rglog.error("业务产品代码为空,需要上送业务产品代码 !");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountRequest.getMchntOrderId())) {
            rglog.error("商户订单号为空,需要上送商户订单号!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (StringUtil.isNullorEmpty(comboMchntFeeDiscountRequest.getTransAmt())) {
            rglog.error("交易金额为空,需要上送交易金额!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (null == comboMchntFeeDiscountRequest.getFeeOrderDetailList() || comboMchntFeeDiscountRequest.getFeeOrderDetailList().isEmpty()) {
            rglog.error("手续费订单明细为空,需上送手续费订单明细!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (!StringUtil.isNullorEmpty(comboMchntFeeDiscountRequest.getStageType()) && !StringUtil.isNullorEmpty(comboMchntFeeDiscountRequest.getStageNum())
                && !StringUtil.isNullorEmpty(comboMchntFeeDiscountRequest.getStageCode())) {
            stageType = comboMchntFeeDiscountRequest.getStageType();
            stageNum = comboMchntFeeDiscountRequest.getStageNum();
            stageCode = comboMchntFeeDiscountRequest.getStageCode();
            rglog.error("该交易为分期业务,分期类型<{}>，分期期数<{}>,分期code<{}>!", stageType, stageNum, stageCode);
        }

        globalInstId = comboMchntFeeDiscountRequest.getHeader().getInstId();
        globalTraceNo = comboMchntFeeDiscountRequest.getHeader().getTraceNo();
        globalTxnDate = comboMchntFeeDiscountRequest.getHeader().getTransDate();
        globalTxnTime = comboMchntFeeDiscountRequest.getHeader().getTransTime();
        globalTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());
        statMfdDayList = new ArrayList<>();
        statMfdList = new ArrayList<>();

        procNormalStatus = false;

        tmTxnOrder = new TMTxnOrder();
        tmTxnOrder.setInstId(globalInstId);
        tmTxnOrder.setTxnDate(globalTxnDate);
        tmTxnOrder.setTxnTime(globalTxnTime);
        tmTxnOrder.setTxnNum(comboMchntFeeDiscountRequest.getHeader().getTxnNum());
        tmTxnOrder.setBizType(comboMchntFeeDiscountRequest.getHeader().getBizType());
        tmTxnOrder.setBizProdCode(comboMchntFeeDiscountRequest.getBizProdCode());
        tmTxnOrder.setMsgSrcId(comboMchntFeeDiscountRequest.getHeader().getSrcSysId());
        tmTxnOrder.setFrontSeqNum(globalTraceNo);
        tmTxnOrder.setOrderId(comboMchntFeeDiscountRequest.getMchntOrderId());
        tmTxnOrder.setUserId(comboMchntFeeDiscountRequest.getUserId());
        tmTxnOrder.setOrderAmt(MompAmountUtil.getTwoDecimal(comboMchntFeeDiscountRequest.getTransAmt()));
        tmTxnOrder.setTxnAmt(CommonConstant.ZERO_AMOUNT);
        tmTxnOrder.setSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        tmTxnOrder.setBankSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        tmTxnOrder.setMchntSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        tmTxnOrder.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
        tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        tmTxnOrder.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        tmTxnOrder.setOrderRemark("{}");
        tmTxnOrder.setOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrder.setCreateTime(globalTimeStamp);
    }

    /**
     * 新增商户手续费减免达标数据统计表数据生成
     *
     * @param mcMchntFeeDiscountTransData 单条记录处理中的数据存储
     * @param tmMcMchntFeeDiscountInfo    商户手续费减免类营销活动信息表
     * @param mchntExpandDate             商户入驻日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdCriteria 手续费减免达标数据统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/7/17 18:05
     */
    private TMStatMfdCriteria processNewMchntCriteriaData(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo, String mchntExpandDate, Boolean notDistinguishMiddleOfMonth) throws Exception {

        String mcNo = tmMcMchntFeeDiscountInfo.getMcNo();
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();
        TMStatMfdCriteria value = null;
        List<TMStatMfdCriteria> tmStatMfdCriteriaList = new ArrayList<>();

        int monthNum = Integer.parseInt(tmMcMchntFeeDiscountInfo.getNewMchntPeriod());

        int year = Integer.parseInt(mchntExpandDate.substring(0, 4));
        int month = Integer.parseInt(mchntExpandDate.substring(4, 6));
        //商户入驻日，用于判断是1号还是15号之后
        int day = Integer.parseInt(mchntExpandDate.substring(6));

        if (notDistinguishMiddleOfMonth) {
            rglog.info("营销活动<{}> 商户<{}> 机构<{}>配置了新商户不区分15号之前之后入驻,继续生成达标统计表数据", mcNo, mchntNo, globalInstId);
        } else {
            rglog.info("营销活动<{}> 商户<{}> 机构下的新商户区分15号之前之后入驻,继续生成达标统计表数据", mcNo, mchntNo);
            if (CommonConstant.MIDDLE_OF_MONTH < day) {
                //如果日期大于15号，则免手续费周期加1
                monthNum++;
            } else {
            }
        }

        String startDate = mchntExpandDate;
        String mcEndDate = tmMcMchntFeeDiscountInfo.getMcEndDate();
        String postponeFlag = tmMcMchntFeeDiscountInfo.getPostponeFlag();
        //活动开始日期
        String mcStartDate = tmMcMchntFeeDiscountInfo.getMcStartDate();

        for (int i = 0; i < monthNum; i++) {
            String periodStartDate = MompDateUtil.getSecondDay(year, month);
            String periodEndDate = MompDateUtil.getNextMonthFirstDay(year, month);
            if (i == 0) {
                //第一个周期，取入驻月份的第一天
                periodStartDate = MompDateUtil.getFirstDay(year, month);
                //第一个周期 判断活动开始日期是否小于第一个周期开始日期
                int code = DateUtil.compareDate(mcStartDate, periodStartDate);
                if (code > 0) {
                    periodStartDate = mcStartDate;
                }
            }
            if (CommonConstant.NEW_MCHNT_DISCOUNT_END.equals(postponeFlag)) {
                /* 如果支持新增商户的营销活动在活动结束后不自动顺延新增商户免手续费的周期，需要判断生成的新商户统计周期是否在活动起止日期内 */
                if (MompDateUtil.checkDateRange(periodEndDate, mcEndDate)) {
                    /* 如果当前生成统计周期在起止日期内，流程正常流转 */
                    //最后一个周期到本月的最后一天 不是下月的1号  --20210305杨斌提出改动，新商户达标统计表最后一个周期不是月底最后一天，应该和其他的一样，为下月的1号
                    //这样新增商户转存量时，周期正好连起来，避免1号时没有营销活动
//                    if (i == monthNum-1){
//                        periodEndDate =MompDateUtil.getMonthTheLastDay(year,month);
//                    }
                } else {
                    /* 如果当前生成统计周期不在起止日期内，需要判断当前周期起始日期是否在营销活动起止日期内 */
                    if (MompDateUtil.checkDateRange(periodStartDate, mcEndDate)) {
                        /* 当前周期起始日期在营销活动起止日期内，当前统计周期开始日期不变，结束日期变为营销活动结束日期 */
                        periodEndDate = mcEndDate;
                    } else {
                        break;
                    }
                }
            } else if (CommonConstant.NEW_MCHNT_DISCOUNT_PROLONG.equals(postponeFlag)) {
                /* 支持新增商户的营销活动在活动结束后自动顺延新增商户免手续费的周期，流程正常流转 */
                //最后一个周期到本月的最后一天 不是下月的1号  --20210305杨斌提出改动，新商户达标统计表最后一个周期不是月底最后一天，应该和其他的一样，为下月的1号
//                if (i == monthNum-1){
//                    periodEndDate =MompDateUtil.getMonthTheLastDay(year,month);
//                }
            } else {
                /* 状态异常 */
                rglog.error("法人机构<{}>的商户手续费优惠活动<{}>的新增商户周期顺延标志数据异常!该营销活动不可对商户<{}>免手续费!", globalInstId, mcNo, mchntNo);
                return null;
            }

            TMStatMfdCriteria tmStatMfdCriteria = new TMStatMfdCriteria();
            tmStatMfdCriteria.setInstId(globalInstId);
            tmStatMfdCriteria.setMcNo(tmMcMchntFeeDiscountInfo.getMcNo());
            tmStatMfdCriteria.setMchntNo(mchntNo);
            tmStatMfdCriteria.setPeriodStartDate(periodStartDate);
            tmStatMfdCriteria.setPeriodEndDate(periodEndDate);
            tmStatMfdCriteria.setRecIndex(String.valueOf(i + 1));
            tmStatMfdCriteria.setBeforeFlag(tmMcMchntFeeDiscountInfo.getBeforeFlag());
            tmStatMfdCriteria.setAfterFlag(tmMcMchntFeeDiscountInfo.getAfterFlag());
            tmStatMfdCriteria.setNewMchntFlag(CommonConstant.MCHNT_NEW_FLAG);
            tmStatMfdCriteria.setNewMchntDate(mchntExpandDate);
            tmStatMfdCriteria.setNewMchntStartDate(startDate);
            tmStatMfdCriteria.setNewMchntEndDate(tmMcMchntFeeDiscountInfo.getRemark1());
            tmStatMfdCriteria.setExitDiscountStatus(CommonConstant.MC_NOT_EXIT_FLAG);
            tmStatMfdCriteria.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdCriteria.setCreateTime(globalTimeStamp);
            tmStatMfdCriteria.setMrctDisUpLmtVal(tmMcMchntFeeDiscountInfo.getNewMchntAmountLimit());

            if (CommonConstant.ZERO == MompDateUtil.checkDateRange(globalTxnDate, periodStartDate, periodEndDate)) {
                value = tmStatMfdCriteria;
                //将手续费减免达标数据统计表转存到对象mcMchntFeeDiscountTransData
                convertMchntFeeDiscountCriteria(tmStatMfdCriteria, mcMchntFeeDiscountTransData);
            }

            tmStatMfdCriteriaList.add(tmStatMfdCriteria);

            if (month >= 12) {
                month = 1;
                year++;
            } else {
                month++;
            }
        }

        /* 插入数据 */
        int returnCode = insertMfdCriteriaData(tmStatMfdCriteriaList);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("将新增商户续费减免达标数据统计表数据插入数据库操作失败! RETURN_CODE=<{}>", returnCode);
            return null;
        } else {
            return value;
        }
    }

    /**
     * 插入新增商户续费减免达标数据统计表数据
     *
     * @param tmStatMfdCriteriaList 手续费减免达标数据统计表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020-07-07 23:02
     */
    private int insertMfdCriteriaData(List<TMStatMfdCriteria> tmStatMfdCriteriaList) throws Exception {

        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        return tmStatMfdCriteriaMapper.insertNewMchntCriteriaData(tmStatMfdCriteriaList);
    }


    /**
     * 取商户手续费优惠类营销活动各维度统计数据
     *
     * @param mcMchntFeeDiscountTransData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/4/20 20:22
     */
    private int fetchAllMchntFeeDiscountMcQuotaData(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {

        //规则维度批量处理状态
        int batchStatus_stat_mfd = CommonConstant.FLAG_NOT_SET;
        int batchStatus_stat_mfd_mchnt = CommonConstant.FLAG_NOT_SET;
        String instId = mcMchntFeeDiscountTransData.getInstId();
        String mcNo = mcMchntFeeDiscountTransData.getMcNo();
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();
        String transDate = mcMchntFeeDiscountTransData.getTransDate();
        String periodStartDate = mcMchntFeeDiscountTransData.getPeriodStartDate();
        String periodEndDate = mcMchntFeeDiscountTransData.getPeriodEndDate();
        String mcStartDate = mcMchntFeeDiscountTransData.getMcStartDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);
        String ruleIndex = mcMchntFeeDiscountTransData.getRuleIndex();
        String mcType = mcMchntFeeDiscountTransData.getMcType();

        /*------------------------------------------------查询营销活动商户维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动商户统计表数据  查询具体规则维度的统计数值*/
        TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
        if (null == tmStatMfdMchnt) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt = new TMStatMfdMchnt();
            tmStatMfdMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
        TMStatMfdMchntDay tmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, transDate);
        if (null == tmStatMfdMchntDay) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
            tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据  规则为0的数据*/
        TMStatMfdMchntDay tmStatMfdMchntDayRuleZero = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, transDate);
        if (null == tmStatMfdMchntDayRuleZero) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero = new TMStatMfdMchntDay();
            tmStatMfdMchntDayRuleZero.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户统计表数据  查询规则为9999的数据，这个统计的是营销活动配置商户退出条件时，统计周期内的所有规则的统计值 如单个商户是季度统计，规则是月度统计，这个9999是当前季度的统计*/
        TMStatMfdMchnt tmStatMfdMchnt9999 = selectNowPeriodDateTMStatMfdMchnt(instId, mcNo, CommonConstant.RULE_NINE, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchnt9999) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, CommonConstant.RULE_NINE);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt9999 = new TMStatMfdMchnt();
            tmStatMfdMchnt9999.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "FeeMchnt" + instId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDay) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
                newtmStatMfdMchntDay = new TMStatMfdMchntDay();
                newtmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            /* 查询商户手续费优惠营销活动商户单日统计表数据  规则为0的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDayRuleZero = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDayRuleZero) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero = new TMStatMfdMchntDay();
                newtmStatMfdMchntDayRuleZero.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, periodStartDate) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，不需要累加到商户统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到商户统计表!", batchDate);
                copyMchntStatMfdData(tmStatMfdMchnt, newtmStatMfdMchntDay);
                copyMchntStatMfdData(tmStatMfdMchnt9999, newtmStatMfdMchntDayRuleZero);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        copyMchntFeeDiscountMchntStatData(tmStatMfdMchnt, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayStatData(tmStatMfdMchntDay, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntStat9999Data(tmStatMfdMchnt9999, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayZeroStatData(tmStatMfdMchntDayRuleZero, mcMchntFeeDiscountTransData);

        /*------------------------------------------------查询营销活动维度汇总数据------------------------------------*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        statPrimaryKey = "Fee" + instId + "_" + mcNo;
        tmStatBak = selectTMStatBakByStatPrimaryKey(instId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        TMStatMfd tmStatMfd = selectMchntFeeDiscountStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
        if (null == tmStatMfd) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动统计表数据查询失败!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfd = new TMStatMfd();
            tmStatMfd.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
        TMStatMfdDay tmStatMfdDay = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, globalTxnDate);
        if (null == tmStatMfdDay) {
            rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay2 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, batchDate);
            if (null == tmStatMfdDay2) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2 = new TMStatMfdDay();
                tmStatMfdDay2.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            copyStatMfdData(tmStatMfd, tmStatMfdDay2);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        //判断本笔交易明细中是否有参加相同活动的商户
        List<TMStatMfdDay> statMfdThisOrderList = statMfdDayList.stream().filter(item -> item.getInstId().equals(instId) && item.getMcNo().equals(mcNo)).collect(Collectors.toList());
        //存在本笔交易同一活动数据
        if (statMfdThisOrderList.size() > 0) {
            //全局变量手续费营销活动单日统计表数据更新已优惠金额
            TMStatMfdDay tmStatMfdThisOrder = statMfdThisOrderList.get(0);
            BigDecimal totalAmtAccThisOrder = new BigDecimal(tmStatMfdThisOrder.getTotalAmtAcc());
            //把本订单使用相同活动的优惠金额累加
            statMfdDayList.stream().filter(item -> item.getInstId().equals(instId) && item.getMcNo().equals(mcNo)).collect(Collectors.toList()).get(0).setTotalAmtAcc(totalAmtAccThisOrder.add(new BigDecimal((mcMchntFeeDiscountTransData.getMchntFeeDiscount()))).toString());
        } else {
            //如果不存在 将子订单set
            TMStatMfdDay tmStatMfdThisOrder = new TMStatMfdDay();
            tmStatMfdThisOrder.setTotalAmtAcc(mcMchntFeeDiscountTransData.getMchntFeeDiscount());
            tmStatMfdThisOrder.setInstId(instId);
            tmStatMfdThisOrder.setMcNo(mcNo);
            statMfdDayList.add(tmStatMfdThisOrder);
        }
        //将累计优惠手续费金额赋值
        copyMchntFeeDiscountZeroStatData(tmStatMfd, tmStatMfdDay, mcMchntFeeDiscountTransData);

        /*------------------------------------------------查询营销活动周期维度汇总数据------------------------------------*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        /* 查询商户手续费减免活动周期统计表数据  规则为0的数据*/
        TMStatMfdPeriod tmStatMfdPeriod = selectMchntFeeDiscountPeriodStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, globalTxnDate, globalTxnDate);
        if (null == tmStatMfdPeriod) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费减免活动周期统计表数据查询结果为空!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdPeriod = new TMStatMfdPeriod();
            tmStatMfdPeriod.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdPeriod.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            //获取不到周期统计数据，默认按照自然月度配置周期起始日期
            tmStatMfdPeriod.setPeriodStartDate(MompDateUtil.getSecondDay(Integer.parseInt(globalTxnDate.substring(0, 4)), Integer.parseInt(globalTxnDate.substring(4, 6))));
        } else {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}> 商户手续费减免活动周期统计表数据查询结束!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
        }

        //根据手续费活动统计表的最后跑批日期判断  批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            rglog.error("机构<{}> 手续费优惠营销活动<{}> 规则<{}> 获取日期为<{}> 手续费减免活动单日统计表数据...", instId, mcNo, ruleIndex, batchDate);
            TMStatMfdDay tmStatMfdDay2 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, batchDate);
            if (null == tmStatMfdDay2) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
                tmStatMfdDay2 = new TMStatMfdDay();
                tmStatMfdDay2.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, tmStatMfdPeriod.getPeriodStartDate()) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，需要累加到周期统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到周期统计表!", batchDate);
                copyMchntFeeDiscountMchntStatData(tmStatMfdPeriod, tmStatMfdDay2);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }
        //将累计优惠手续费金额赋值——周期维度判断使用
        copyMchntFeeDiscountPeriodZeroStatData(tmStatMfdPeriod, tmStatMfdDay, mcMchntFeeDiscountTransData);

        return CommonConstant.ZERO;
    }

    /**
     * 商户手续费优惠类营销活动交易限额处理
     *
     * @param mcMchntFeeDiscountTransData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/4/21 09:36
     */
    private int checkMchntFeeDiscountLimits(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail) throws Exception {

        String instId = mcMchntFeeDiscountTransData.getInstId();
        String mcNo = mcMchntFeeDiscountTransData.getMcNo();
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();
        String mchntName = mcMchntFeeDiscountTransData.getMchntName();
        String signInstId = mcMchntFeeDiscountTransData.getSignInstId();
        //推送标志
        int pushFlag = CommonConstant.FLAG_NOT_SET;
        //不包含本笔剩余可优惠交易金额
        BigDecimal beforeDiscount;
        //包含本笔剩余可优惠交易金额
        BigDecimal afterDiscount;
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam messageSysParam = sysParamService.getSysParamInfo(globalInstId, "MOMP_MSG_PUSH", "MOMP_MSG_PUSH");
        //本笔手续费优惠订单金额
        BigDecimal orderAmt = new BigDecimal(feeOrderDetail.getMchntSettleAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        //本次手续费优惠金额
        BigDecimal totalSubsidy = new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeDiscount()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        //手续费减免活动商户统计-累计交易金额
        BigDecimal txnAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTxnAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户单日统计数据 具体规则-累计交易金额
        BigDecimal txnAmtAccDay = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTxnAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        /* 判断单个商户营销活动优惠退出条件 */
        String terminationFlag = mcMchntFeeDiscountTransData.getTerminationFlag();
        //优惠退出条件 手续优惠剩余额度
        BigDecimal remainingQuota = totalSubsidy;
        //剩余的可优惠交易额
        BigDecimal remainderDiscountAmt = orderAmt;
        //是否需要重新计算手续费
        boolean recalculate = false;
        switch (terminationFlag) {
            case CommonConstant.MCHNT_FEE_EXIT_NORMAL:
                /* 不需要判断优惠退出条件 */
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>不需要判断商户优惠退出条件!商户<{}>可继续检查后续限额!", instId, mcNo, mchntNo);
                break;
            case CommonConstant.MCHNT_FEE_EXIT_UNDER_CONDITION:
                /* 需要判断优惠退出条件 */
                String statPeriod = mcMchntFeeDiscountTransData.getStatPeriod();
                if (CommonConstant.FEE_EXIT_MC.equals(statPeriod) || CommonConstant.FEE_EXIT_MONTH.equals(statPeriod) ||
                        CommonConstant.FEE_EXIT_QUARTER.equals(statPeriod) || CommonConstant.FEE_EXIT_ANNUAL.equals(statPeriod)) {
                    //累计优惠笔数
                    BigDecimal totalQtyAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalQtyAcc9999()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
                    //累计优惠金额
                    BigDecimal totalAmtAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalAmtAcc9999()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                    //累计交易金额
                    BigDecimal txnAmtAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTxnAmtAcc9999()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                    //手续费减免活动商户单日统计数据 规则为0-累计优惠笔数
                    BigDecimal totalQtyAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalQtyAccZero()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
                    //手续费减免活动商户单日统计数据 规则为0-累计优惠金额
                    BigDecimal totalAmtAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalAmtAccZero()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                    //手续费减免活动商户单日统计数据 规则为0-累计交易金额
                    BigDecimal txnAmtAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTxnAmtAccZero()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                    /* 单个商户优惠交易笔数上限 */
                    BigDecimal quantityLimit = new BigDecimal(mcMchntFeeDiscountTransData.getQuantityLimit()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
                    /* 单个商户优惠交易金额上限 */
                    BigDecimal amountLimit = new BigDecimal(mcMchntFeeDiscountTransData.getAmountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                    /* 单个商户手续费优惠额上限 */
                    BigDecimal feeLimit = new BigDecimal(mcMchntFeeDiscountTransData.getFeeLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                    /* 与手续费减免活动商户统计表+手续费减免活动商户单日统计表数据对比 */
                    if (BigDecimal.ZERO.compareTo(quantityLimit) >= CommonConstant.ZERO) {
                        rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>不需要判断单个商户优惠交易笔数上限!可继续检查后续限额!", instId, mcNo, mchntNo);
                    } else {
                        if (CommonConstant.ZERO < quantityLimit.compareTo(totalQtyAcc9999.add(totalQtyAccDayZero).add(BigDecimal.ONE))) {
                            /* 本笔交易未超过限制,可优惠 */
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}>未超过单个商户优惠交易笔数上限<{}>，加本次<{}>!可继续检查后续限额!", instId, mcNo, mchntNo, quantityLimit, totalQtyAcc9999.add(totalQtyAccDayZero).add(BigDecimal.ONE));
                        } else if (CommonConstant.ZERO == quantityLimit.compareTo(totalQtyAcc9999.add(totalQtyAccDayZero).add(BigDecimal.ONE))) {
                            /* 本笔交易未超过限制,可优惠 ,本笔交易正好达到限制 */
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}>本笔交易后正好达到优惠交易笔数上限最大限制<{}>!流程继续!", instId, mcNo, mchntNo, quantityLimit);

                            mcMchntFeeDiscountTransData.setExitTxnQtyFlag(CommonConstant.ONE_COMMON_CONSTANT);
                        } else {
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}>已超过单个商户优惠交易笔数上限<{}>,加本次<{}>!", instId, mcNo, mchntNo, quantityLimit, totalQtyAcc9999.add(totalQtyAccDayZero).add(BigDecimal.ONE));
                            return CommonConstant.ONE;
                        }
                    }

                    if (BigDecimal.ZERO.compareTo(amountLimit) >= CommonConstant.ZERO) {
                        rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>不需要判断单个商户优惠交易金额上限!可继续检查后续限额!", instId, mcNo, mchntNo);
                    } else {
                        beforeDiscount = amountLimit.subtract(txnAmtAcc9999).subtract(txnAmtAccDayZero);
                        afterDiscount = amountLimit.subtract(txnAmtAcc9999).subtract(txnAmtAccDayZero).subtract(orderAmt);
                        if (CommonConstant.ZERO < amountLimit.compareTo(orderAmt.add(txnAmtAcc9999).add(txnAmtAccDayZero))) {
                            /* 本笔交易未超过限制,可优惠 */
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}>未超过单个商户优惠交易金额上限<{}>,加本次<{}>!可继续检查后续限额!", instId, mcNo, mchntNo, amountLimit, orderAmt.add(txnAmtAcc9999).add(txnAmtAccDayZero));
                        } else if (CommonConstant.ZERO == amountLimit.compareTo(orderAmt.add(txnAmtAcc9999).add(txnAmtAccDayZero))) {
                            /* 本笔交易未超过限制,可优惠 ,本笔交易正好达到限制 */
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}>本笔交易后正好达到单个商户优惠交易金额上限<{}>!可继续检查后续限额!", instId, mcNo, mchntNo, amountLimit);
                            mcMchntFeeDiscountTransData.setExitTxnAmtFlag(CommonConstant.ONE_COMMON_CONSTANT);
                        } else if (CommonConstant.ZERO > amountLimit.compareTo(orderAmt.add(txnAmtAcc9999).add(txnAmtAccDayZero)) &&
                                CommonConstant.ZERO < amountLimit.compareTo(txnAmtAcc9999.add(txnAmtAccDayZero))) {
                            /* 不加本笔交易未超过限制，加上本笔交易超过限制*/
                            //剩余的可优惠交易金额
                            remainderDiscountAmt = amountLimit.subtract(txnAmtAcc9999.add(txnAmtAccDayZero));
                            //需要重新计算手续费
                            recalculate = true;
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}> 单个商户优惠交易金额上限<{}>,加本笔累计交易金额为<{}> 所以本笔交易剩余可优惠交易金额为<{}>!",
                                    instId, mcNo, mchntNo, amountLimit, orderAmt.add(txnAmtAcc9999).add(txnAmtAccDayZero), remainderDiscountAmt);

                            mcMchntFeeDiscountTransData.setExitTxnAmtFlag(CommonConstant.ONE_COMMON_CONSTANT);
                        } else {
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}>已超过单个商户优惠交易金额上限<{}>,不加本次总额<{}> 加本次总额<{}>!",
                                    instId, mcNo, mchntNo, amountLimit, txnAmtAcc9999.add(txnAmtAccDayZero), orderAmt.add(txnAmtAcc9999).add(txnAmtAccDayZero));
                            return CommonConstant.ONE;
                        }
                        //优惠前剩余可优惠交易金额大于等于10000 优惠后剩余可优惠交易金额小于10000
                        if (beforeDiscount.compareTo(new BigDecimal(10000)) >= 0 && afterDiscount.compareTo(new BigDecimal(10000)) < 0) {
                            rglog.info("优惠前剩余可优惠交易金额<{}>大于等于10000,优惠后剩余可优惠交易金额<{}>小于10000。判断该行<{}>是否配置微信消息推送", beforeDiscount, afterDiscount, globalInstId);
                            //判断该行是否配置了消息推送
                            if (null != messageSysParam) {
                                rglog.info("调用短信推送");
                                //TODO 调用短信推送
                                pushFlag = CommonConstant.FLAG_SET;
                            } else {
                                rglog.info("未配置短信配送！！！");
                            }
                        }
                    }

                    if (BigDecimal.ZERO.compareTo(feeLimit) >= CommonConstant.ZERO) {
                        rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>不需要判断单个商户手续费优惠额上限!可继续检查后续限额!", instId, mcNo, mchntNo);
                        break;
                    } else {
                        if (CommonConstant.ZERO < feeLimit.compareTo(totalSubsidy.add(totalAmtAcc9999).add(totalAmtAccDayZero))) {
                            remainingQuota = totalSubsidy;
                            /* 本笔交易未超过限制,可优惠 */
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}>未超过单个商户手续费优惠额上限<{}>!,加本次<{}>可继续检查后续限额!", instId, mcNo, mchntNo, feeLimit, totalSubsidy.add(totalAmtAcc9999).add(totalAmtAccDayZero));
                        } else if (CommonConstant.ZERO == feeLimit.compareTo(totalSubsidy.add(totalAmtAcc9999).add(totalAmtAccDayZero))) {
                            remainingQuota = totalSubsidy;
                            /* 本笔交易未超过限制,可优惠 ,本笔交易正好达到限制 */
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}>本笔交易后正好达到单个商户手续费优惠额上限<{}>!", instId, mcNo, mchntNo, feeLimit);
                            mcMchntFeeDiscountTransData.setExitDiscountFlag(CommonConstant.ONE_COMMON_CONSTANT);
                        } else if (CommonConstant.ZERO <= feeLimit.compareTo(totalAmtAcc9999.add(totalAmtAccDayZero)) && CommonConstant.ZERO > feeLimit.compareTo(totalSubsidy.add(totalAmtAcc9999).add(totalAmtAccDayZero))) {
                            /* 本笔交易超过限制但存在剩余优惠额度,可优惠 */
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}>本笔交易后超过单个商户手续费优惠额上限<{}>但存在可优惠额度!", instId, mcNo, mchntNo, feeLimit);
                            mcMchntFeeDiscountTransData.setExitDiscountFlag(CommonConstant.ONE_COMMON_CONSTANT);
                            remainingQuota = feeLimit.subtract(totalAmtAcc9999.add(totalAmtAccDayZero)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        } else {
                            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>的商户<{}>已超过单个商户手续费优惠额上限<{}>,加本次<{}>!", instId, mcNo, mchntNo, feeLimit, totalSubsidy.add(totalAmtAcc9999).add(totalAmtAccDayZero));
                            return CommonConstant.ONE;
                        }
                    }
                    break;
                } else {
                    /* 不需要判断优惠退出条件 */
                    rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>不需要判断商户优惠退出条件!商户<{}>可继续检查后续限额!", instId, mcNo, mchntNo);
                    break;
                }
            default:
                rglog.debug("营销活动优惠退出条件类型<{}>错误!", terminationFlag);
                return CommonConstant.ONE;
        }

        //获取规则上限类型，如果规则上限是手续费金额，则需要判手续费上限
        String ruleType = mcMchntFeeDiscountTransData.getCalRuleNo();
        //指定优惠手续费金额具体数值
        if (FeeCalTypeEnum.TYPE_13.getRuleType().equals(ruleType)) {
            MchntFeeCheckLimitService mchntFeeCheckLimitService = new MchntFeeCheckLimitService();
            Object obj = mchntFeeCheckLimitService.checkMfdRuleTotalAmtAndBudgetLimit(mcMchntFeeDiscountTransData, remainingQuota, rglog);
            //如果返回结果为空，则已经超限，直接返回不可优惠
            if (null == obj) {
                return CommonConstant.ONE;
            } else {
                McMchntFeeDiscountTransData newMcMchntFeeDiscountTransData = (McMchntFeeDiscountTransData) obj;
                //如果正常返回，重新给当前计算流程中使用的实体赋优惠手续费的值
                mcMchntFeeDiscountTransData.setMchntFeeDiscount(newMcMchntFeeDiscountTransData.getMchntFeeDiscount());
                //重新给实收手续费赋值
                mcMchntFeeDiscountTransData.setMchntFeeActual(new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeReceivable()).subtract(new BigDecimal(newMcMchntFeeDiscountTransData.getMchntFeeDiscount())).toString());
            }
        } else {
            /* 判断规则优惠上限是否超限 */
            BigDecimal discountLimit = new BigDecimal(mcMchntFeeDiscountTransData.getDiscountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //本笔交易金额 + 周期统计累计优惠金额 + 单日统计累计优惠金额
            BigDecimal totalDiscount = remainderDiscountAmt.add(txnAmtAcc).add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //周期统计累计优惠金额 + 单日统计累计优惠金额
            BigDecimal historyTotalDiscount = txnAmtAcc.add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            //不包含本笔交易金额
            BigDecimal discount = txnAmtAcc.add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            rglog.info("规则优惠上限<{}>,加本笔总优惠金额<{}>，不加本笔总优惠金额<{}>", discountLimit, totalDiscount, discount);
            //应收手续费
            BigDecimal mchntFeeReceivable = new BigDecimal(feeOrderDetail.getMchntFeeReceivable());
            //不包含本笔剩余可优惠交易金额
            beforeDiscount = discountLimit.subtract(txnAmtAcc).subtract(txnAmtAccDay);
            //包含本笔剩余可优惠交易金额
            afterDiscount = discountLimit.subtract(txnAmtAcc).subtract(txnAmtAccDay).subtract(orderAmt);
            if (CommonConstant.ZERO <= discountLimit.compareTo(totalDiscount)) {
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>规则<{}>加本次已优惠<{}>优惠上限<{}>校验通过，未超规则限额!流程继续！", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), totalDiscount, discountLimit);
                /* 限额大于等于累计优惠金额(当前包含本笔优惠金额),可以优惠 */
                if (CommonConstant.ZERO >= remainingQuota.compareTo(totalSubsidy)) {
                    totalSubsidy = remainingQuota;
                    rglog.info("判断是否配置了单个商户手续费优惠上限，超额后重新给手续费优惠赋值了，原计划优惠金额<{}>,判断后优惠金额<{}>", totalSubsidy, remainingQuota);
                    //重新给优惠手续费金额赋值
                    mcMchntFeeDiscountTransData.setMchntFeeDiscount(remainingQuota.toString());
                    //重新给实收手续费赋值
                    mcMchntFeeDiscountTransData.setMchntFeeActual(mchntFeeReceivable.subtract(remainingQuota).toString());
                }
                if (pushFlag == CommonConstant.FLAG_NOT_SET) {
                    //优惠前剩余可优惠交易金额大于等于10000 优惠后剩余可优惠交易金额小于10000
                    if (beforeDiscount.compareTo(new BigDecimal(10000)) >= 0 && afterDiscount.compareTo(new BigDecimal(10000)) < 0) {
                        rglog.info("优惠前剩余可优惠交易金额<{}>大于等于10000,优惠后剩余可优惠交易金额<{}>小于10000。判断该行<{}>是否配置微信消息推送", beforeDiscount, afterDiscount, globalInstId);
                        //判断该行是否配置了消息推送
                        if (null != messageSysParam) {
                            rglog.info("调用短信推送");
                            //TODO 调用短信推送
                        } else {
                            rglog.info("未配置短信配送！！！");
                        }
                    }
                }
                //判断是否超出预算资金
                rglog.info("判断加上本笔手续费优惠金额是否超出预算资金");
                //总预算
                BigDecimal budget = new BigDecimal(mcMchntFeeDiscountTransData.getBudget());
                if (budget.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
                    //总预算累计消耗金额  包含统计表+单日+本流水除本明细外的所有金额
                    BigDecimal mcTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMcTotalAmtAcc());
                    //加本笔明细的汇总
                    BigDecimal mcTotalAmtAccAddThisDet = mcTotalAmtAcc.add(new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeDiscount()));

                    if (CommonConstant.ZERO <= budget.compareTo(mcTotalAmtAccAddThisDet)) {
                        rglog.info("商户<{}>匹配到营销活动<{}>已累计优惠手续费金额<{}>加上本笔优惠手续费金额<{}>未超出总预算<{}>,给予优惠！！！", mcMchntFeeDiscountTransData.getMchntNo(), mcMchntFeeDiscountTransData.getMcNo(), mcTotalAmtAcc, mcTotalAmtAccAddThisDet, mcMchntFeeDiscountTransData.getBudget());
                    } else {
                        rglog.info("加上本笔手续费优惠金额交易超出预算资金，继续判断不加本笔手续费优惠金额是否超出预算资金");
                        if (CommonConstant.ZERO >= budget.compareTo(mcTotalAmtAcc)) {
                            rglog.info("商户<{}>匹配到营销活动<{}>已累计优惠手续费金额<{}>加上本笔优惠手续费金额<{}>超出总预算<{}>,不予优惠！！！", mcMchntFeeDiscountTransData.getMchntNo(), mcMchntFeeDiscountTransData.getMcNo(), mcTotalAmtAcc, mcTotalAmtAccAddThisDet, mcMchntFeeDiscountTransData.getBudget());
                            return CommonConstant.ONE;
                        } else {
                            rglog.info("商户<{}>匹配到营销活动<{}>已累计优惠手续费金额<{}>加上本笔优惠手续费金额<{}>未超过总预算<{}>,仅可优惠<{}>！！！", mcMchntFeeDiscountTransData.getMchntNo(), mcMchntFeeDiscountTransData.getMcNo(), mcTotalAmtAcc, mcTotalAmtAccAddThisDet, mcMchntFeeDiscountTransData.getBudget(), budget.subtract(mcTotalAmtAcc));
                            mcMchntFeeDiscountTransData.setMchntFeeDiscount(budget.subtract(mcTotalAmtAcc).toString());
                            //重新给实收手续费赋值
                            mcMchntFeeDiscountTransData.setMchntFeeActual(new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeReceivable()).subtract(budget.subtract(mcTotalAmtAcc)).toString());
                        }
                    }
                } else {
                    rglog.info("默认预算资金无上限,不判断是否超出预算资金");
                }
            } else if (CommonConstant.ZERO < discountLimit.compareTo(historyTotalDiscount)) {
                /* 不加本笔交易规则维度未超过限制，加上本笔交易超过限制*/
                //剩余的可优惠交易金额
                remainderDiscountAmt = remainderDiscountAmt.compareTo(discountLimit.subtract(historyTotalDiscount)) <= 0 ? remainderDiscountAmt : discountLimit.subtract(historyTotalDiscount);
                //需要重新计算手续费
                recalculate = true;
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>规则<{}> 商户加本次已优惠<{}> 优惠上限<{}> 已超过上限值，本次交易仅可优惠的交易金额为<{}>！",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), totalDiscount, discountLimit, remainderDiscountAmt);

                mcMchntFeeDiscountTransData.setExitTxnAmtFlag(CommonConstant.ONE_COMMON_CONSTANT);
            } else {
                /* 限额小于累计优惠金额(当前包含本笔优惠金额),不可以优惠 */
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>规则<{}>加本次已优惠<{}>优惠上限<{}>校验失败，已超规则限额!", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), totalDiscount, discountLimit);
                return CommonConstant.ONE;
            }
        }

        //需要重新计算手续费（以上判断商户剩余优惠金或者规则额度不满足本笔的交易金额）
        if (recalculate) {
            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> ，存在剩余额度，但不是所有金额都享受手续费优惠，开始重新计算手续费!", instId, mcNo);
            //重新计算手续费
            boolean recalculateMchntFee = recalculateMchntFee(mcMchntFeeDiscountTransData, orderAmt, remainderDiscountAmt, feeOrderDetail, CommonConstant.ONE_COMMON_CONSTANT);
            if (recalculateMchntFee) {
                //商户优惠交易金额 */
                mcMchntFeeDiscountTransData.setMchntFeeDiscountTransAmt(remainderDiscountAmt.toString());
            } else {
                rglog.info("商户<{}> 重新计算手续费优惠失败，无手续费优惠!!!");
                return CommonConstant.ONE;
            }
        }

        return CommonConstant.ZERO;
    }

    /**
     * 使用主键取手续费减免活动统计表单条数据
     *
     * @param instId    法人机构编号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @return cc.rengu.igas.momp.common.entity.TMStatMfd 手续费减免活动统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/4/20 22:42selectMchntFeeDiscountMchntDayStatisticsByPK
     */
    private TMStatMfd selectMchntFeeDiscountStatisticsByPK(String instId, String mcNo, String ruleIndex) throws Exception {

        TMStatMfdMapper tmStatMfdMapper = new TMStatMfdMapperImpl();
        return tmStatMfdMapper.selectMchntFeeDiscountStatisticsByPK(instId, mcNo, ruleIndex);
    }

    /**
     * 使用主键取手续费减免活动商户单日统计表单条数据
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @param mchntNo   商户编号
     * @param txnDate   交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchntDay 手续费减免活动商户单日统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/4/20 23:42
     */
    private TMStatMfdMchntDay selectMchntFeeDiscountMchntDayStatisticsByPK(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        return tmStatMfdMchntDayMapper.selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 手续费减免活动统计数据赋值
     *
     * @param tmStatMfd                   手续费减免活动统计表
     * @param mcMchntFeeDiscountTransData 数据库操作对象
     * @author liujinan
     * @since 2020/6/5 11:23
     */
    private void copyMchntFeeDiscountStatData(TMStatMfd tmStatMfd, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /*  手续费减免活动统计-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMcTotalQtyAcc(tmStatMfd.getTotalQtyAcc());
        /*  手续费减免活动统计-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMcTotalAmtAcc(tmStatMfd.getTotalAmtAcc());
        /*  手续费减免活动统计-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMcTxnQtyAcc(tmStatMfd.getTxnQtyAcc());
        /*  手续费减免活动统计-累计交易金额 */
        mcMchntFeeDiscountTransData.setMcTxnAmtAcc(tmStatMfd.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动周期统计数据赋值
     *
     * @param tmStatMfdPeriod             手续费减免活动周期统计表
     * @param mcMchntFeeDiscountTransData 数据库操作对象
     * @author liujinan
     * @since 2020/6/5 11:23
     */
    private void copyMchntFeeDiscountPeriodStatData(TMStatMfdPeriod tmStatMfdPeriod, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动周期统计-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setPeriodTotalQtyAcc(tmStatMfdPeriod.getTotalQtyAcc());
        /* 手续费减免活动周期统计-累计优惠金额 */
        mcMchntFeeDiscountTransData.setPeriodTotalAmtAcc(tmStatMfdPeriod.getTotalAmtAcc());
        /* 手续费减免活动周期统计-累计交易笔数 */
        mcMchntFeeDiscountTransData.setPeriodTxnQtyAcc(tmStatMfdPeriod.getTxnQtyAcc());
        /* 手续费减免活动周期统计-累计交易金额 */
        mcMchntFeeDiscountTransData.setPeriodTxnAmtAcc(tmStatMfdPeriod.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动单日统计数据赋值
     *
     * @param tmStatMfdDay                手续费减免活动单日统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/6/5 11:23
     */
    private void copyMchntFeeDiscountSingleDayStatData(TMStatMfdDay tmStatMfdDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动单日统计-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setDayTotalQtyAcc(tmStatMfdDay.getTotalQtyAcc());
        /* 手续费减免活动单日统计-累计优惠金额 */
        mcMchntFeeDiscountTransData.setDayTotalAmtAcc(tmStatMfdDay.getTotalAmtAcc());
        /* 手续费减免活动单日统计-累计交易笔数 */
        mcMchntFeeDiscountTransData.setDayTxnQtyAcc(tmStatMfdDay.getTxnQtyAcc());
        /* 手续费减免活动单日统计-累计交易金额 */
        mcMchntFeeDiscountTransData.setDayTxnAmtAcc(tmStatMfdDay.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户统计数据赋值
     *
     * @param tmStatMfdMchnt              手续费减免活动商户统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/6/5 11:23
     */
    private void copyMchntFeeDiscountMchntStatData(TMStatMfdMchnt tmStatMfdMchnt, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户统计-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntTotalQtyAcc(tmStatMfdMchnt.getTotalQtyAcc());
        /* 手续费减免活动商户统计-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntTotalAmtAcc(tmStatMfdMchnt.getTotalAmtAcc());
        /* 手续费减免活动商户统计-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntTxnQtyAcc(tmStatMfdMchnt.getTxnQtyAcc());
        /* 手续费减免活动商户统计-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntTxnAmtAcc(tmStatMfdMchnt.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户单日统计数据赋值
     *
     * @param tmStatMfdMchntDay           手续费减免活动商户单日统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/6/5 11:22
     */
    private void copyMchntFeeDiscountMchntDayStatData(TMStatMfdMchntDay tmStatMfdMchntDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户单日统计数据-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTotalQtyAcc(tmStatMfdMchntDay.getTotalQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntDayTotalAmtAcc(tmStatMfdMchntDay.getTotalAmtAcc());
        /* 手续费减免活动商户单日统计数据-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTxnQtyAcc(tmStatMfdMchntDay.getTxnQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntDayTxnAmtAcc(tmStatMfdMchntDay.getTxnAmtAcc());
    }

    /**
     * 计算优惠手续费和实收手续费
     *
     * @param mcMchntFeeDiscountTransData 商户手续费优惠交易中使用的的实体
     * @return java.lang.String 手续费优惠金额
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/4/20 21:42
     */
    private String calculateMchntFeeDiscountSubsidy(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail) throws Exception {

        /* 判断计算类型 */
        BigDecimal thousand = new BigDecimal(CommonConstant.THOUSAND);
        /* 手续费收取方式 */
        String feeInputMode = feeOrderDetail.getFeeInputMode();
        /* 应收手续费 */
        BigDecimal mchntFeeReceivable = new BigDecimal(CommonConstant.ZERO_AMOUNT_FEE);
//        /* 应收手续费费率 */
//        BigDecimal mchntFeeReceivableRate = new BigDecimal(feeOrderDetail.getMchntFeeReceivableRate()).divide(thousand);
        /* 订单金额 */
        BigDecimal orderAmt = new BigDecimal(feeOrderDetail.getMchntSettleAmt());

        /* 手续费优惠类型 */
        String discountType = mcMchntFeeDiscountTransData.getDiscountType();
        /* 优惠手续费 */
        BigDecimal mchntFeeDiscount;
        /* 实收手续费 */
        BigDecimal mchntFeeActual;
        /* 优惠力度 */
        BigDecimal discount;

        //当手续费收取方式feeInputMode为手工输入按固定金额时，接口不上送费率值，在这默认赋值为0；
        if (CommonConstant.TWO_COMMON_CONSTANT.equals(feeInputMode)) {
            feeOrderDetail.setMchntFeeReceivableRate(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        //当前手续费收取方式-使用现有费率时，接口不上送 商户应收手续费金额	mchntFeeReceivable  和 商户应收手续费费率	mchntFeeReceivableRate
        if (!CommonConstant.FEE_MODE_LADDER.equals(feeInputMode)) {
            mchntFeeReceivable = new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeReceivable());
        }

        switch (feeInputMode) {
            case CommonConstant.FEE_MODE_LADDER:
                /* 使用现有费率 */
                rglog.error("商户<{}>,手续费收取方式<{}>-使用现有费率,不支持配置费率模板方式的商户手续费优惠计算!!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode);
                mchntFeeDiscount = BigDecimal.ZERO;
                mchntFeeActual = mchntFeeReceivable;
                break;
            case CommonConstant.FEE_MODE_RATE:
                /* 手工输入按比率 */
                switch (discountType) {
                    case CommonConstant.MCHNT_FEE_FREE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-免手续费!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode, discountType);
                        /* 手续费全免,实收为0,优惠=应收 */
                        mchntFeeDiscount = mchntFeeReceivable;
                        mchntFeeActual = BigDecimal.ZERO;
                        break;
                    case CommonConstant.MCHNT_FEE_DISCOUNT:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-费率打折!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode, discountType);
                        /* 费率打折,实收=应收*折扣,优惠=应收-实收 */
                        discount = new BigDecimal(mcMchntFeeDiscountTransData.getDiscount());
                        mchntFeeActual = mchntFeeReceivable.multiply(discount).divide(BigDecimal.TEN).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        mchntFeeDiscount = mchntFeeReceivable.subtract(mchntFeeActual);
                        break;
                    case CommonConstant.MCHNT_FEE_FIXED_RATE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-固定费率!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode, discountType);
                        //判断固定费率和应收费率的大小，如果固定费率大于应收，则没有优惠
                        if (new BigDecimal(mcMchntFeeDiscountTransData.getDiscount()).compareTo(new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeReceivableRate())) >= CommonConstant.ZERO) {
                            rglog.info("手工输入按比率,活动固定费率<{}> 接口请求上送应收费率<{}>，无手续费优惠", mcMchntFeeDiscountTransData.getDiscount(), mcMchntFeeDiscountTransData.getMchntFeeReceivableRate());
//                            return CommonConstant.ONE;
                            mchntFeeDiscount = BigDecimal.ZERO;
                            mchntFeeActual = mchntFeeReceivable;
                            break;
                        }
                        /* 固定费率,实收=订单金额*优惠费率,优惠=应收-实收 */
                        discount = new BigDecimal(mcMchntFeeDiscountTransData.getDiscount()).divide(thousand);
                        mchntFeeActual = orderAmt.multiply(discount).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        mchntFeeDiscount = mchntFeeReceivable.subtract(mchntFeeActual);
                        break;
                    default:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率,商户手续费优惠类型<{}>-优惠类型异常!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode, discountType);
                        mchntFeeDiscount = BigDecimal.ZERO;
                        mchntFeeActual = mchntFeeReceivable;
                        break;
                }
                break;
            case CommonConstant.FEE_MODE_FIXED_AMT:
                /* 手工输入按固定金额 */
                switch (discountType) {
                    case CommonConstant.MCHNT_FEE_FREE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按固定金额,商户手续费优惠类型<{}>-免手续费!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode, discountType);
                        /* 手续费全免,实收为0,优惠=应收 */
                        mchntFeeDiscount = mchntFeeReceivable;
                        mchntFeeActual = BigDecimal.ZERO;
                        break;
                    case CommonConstant.MCHNT_FEE_DISCOUNT:
                    case CommonConstant.MCHNT_FEE_FIXED_RATE:
                        /* 手工输入按固定金额,不支持费率打折或固定费率的优惠方式 */
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按固定金额,商户手续费优惠类型<{}>-不可使用费率打折或固定费率的商户手续费优惠方式!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode, discountType);
                        mchntFeeDiscount = BigDecimal.ZERO;
                        mchntFeeActual = mchntFeeReceivable;
                        break;
                    default:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按固定金额,商户手续费优惠类型<{}>-优惠类型异常!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode, discountType);
                        mchntFeeDiscount = BigDecimal.ZERO;
                        mchntFeeActual = mchntFeeReceivable;
                        break;
                }
                break;
            case CommonConstant.FEE_MODE_RATE_AMT:
                /* 手工输入按比率+封顶值 */
                switch (discountType) {
                    case CommonConstant.MCHNT_FEE_FREE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-免手续费!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode, discountType);
                        /* 手续费全免,实收为0,优惠=应收 */
                        mchntFeeDiscount = mchntFeeReceivable;
                        mchntFeeActual = BigDecimal.ZERO;
                        break;
                    case CommonConstant.MCHNT_FEE_DISCOUNT:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-费率打折!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode, discountType);
                        /* 费率打折,实收=min(订单金额*费率*折扣,应收),优惠=应收-实收 */
                        /* 应收手续费费率 */
                        BigDecimal mchntFeeReceivableRate = new BigDecimal(feeOrderDetail.getMchntFeeReceivableRate()).divide(thousand);
                        discount = new BigDecimal(mcMchntFeeDiscountTransData.getDiscount());
                        mchntFeeActual = orderAmt.multiply(mchntFeeReceivableRate).multiply(discount).divide(BigDecimal.TEN).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        mchntFeeActual = mchntFeeActual.min(mchntFeeReceivable);
                        mchntFeeDiscount = mchntFeeReceivable.subtract(mchntFeeActual);
                        break;
                    case CommonConstant.MCHNT_FEE_FIXED_RATE:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-固定费率!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode, discountType);
                        //判断固定费率和应收费率的大小，如果固定费率大于应收，则没有优惠
                        if (new BigDecimal(mcMchntFeeDiscountTransData.getDiscount()).compareTo(new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeReceivableRate())) >= CommonConstant.ZERO) {
                            rglog.info("手工输入按比率,活动固定费率<{}> 接口请求上送应收费率<{}>，无手续费优惠", mcMchntFeeDiscountTransData.getDiscount(), mcMchntFeeDiscountTransData.getMchntFeeReceivableRate());
//                            return CommonConstant.ONE;
                            mchntFeeDiscount = BigDecimal.ZERO;
                            mchntFeeActual = mchntFeeReceivable;
                            break;
                        }
                        /* 固定费率,实收=min(订单金额*优惠费率,应收),优惠=应收-实收 */
                        discount = new BigDecimal(mcMchntFeeDiscountTransData.getDiscount()).divide(thousand);
                        mchntFeeActual = orderAmt.multiply(discount).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        mchntFeeActual = mchntFeeActual.min(mchntFeeReceivable);
                        mchntFeeDiscount = mchntFeeReceivable.subtract(mchntFeeActual);
                        break;
                    default:
                        rglog.info("商户<{}>,手续费收取方式<{}>-手工输入按比率+封顶值,商户手续费优惠类型<{}>-优惠类型异常!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode, discountType);
                        mchntFeeDiscount = BigDecimal.ZERO;
                        mchntFeeActual = mchntFeeReceivable;
                        break;
                }
                break;
            default:
                rglog.info("商户<{}>,手续费收取方式<{}>-手续费收取方式异常!", mcMchntFeeDiscountTransData.getMchntNo(), feeInputMode);
                mchntFeeDiscount = BigDecimal.ZERO;
                mchntFeeActual = mchntFeeReceivable;
                break;
        }

        mcMchntFeeDiscountTransData.setMchntFeeDiscount(mchntFeeDiscount.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        mcMchntFeeDiscountTransData.setMchntFeeActual(mchntFeeActual.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());

        return mchntFeeDiscount.toString();
    }

    /**
     * 校验手续费优惠达标统计表中的达标状态和退出状态
     *
     * @param tmStatMfdCriteria 手续费优惠达标统计表 数据
     * @author liujinan
     * @since 2020/7/21 17:23
     */
    private int checkExitFlagAndCriteriaFlag(TMStatMfdCriteria tmStatMfdCriteria) {

        String criteriaFlag = tmStatMfdCriteria.getCriteriaFlag();
        String exitFlag = tmStatMfdCriteria.getExitDiscountStatus();

        if (CommonConstant.ZERO_COMMON_CONSTANT.equals(criteriaFlag)) {
            rglog.error("机构<{}> 商户<{}>,存量商户达标标志<{}>，未达标!", globalInstId, tmStatMfdCriteria.getMchntNo(), criteriaFlag);

            return CommonConstant.ONE;
        }

        if (CommonConstant.ONE_COMMON_CONSTANT.equals(exitFlag)) {
            rglog.error("机构<{}> 商户<{}>,优惠退出状态<{}>，已退出优惠!", globalInstId, tmStatMfdCriteria.getMchntNo(), exitFlag);
            return CommonConstant.ONE;
        }

        rglog.info("机构<{}> 商户<{}>,手续费优惠存量商户（或新入驻商户）达标标志已达标，未退出优惠状态，流程继续", globalInstId, tmStatMfdCriteria.getMchntNo());
        return CommonConstant.ZERO;
    }

    /**
     * 记录没有优惠的订单明细
     *
     * @param feeOrderDetail 订单手续费优惠对象
     * @author liujinan
     * @since 2020/7/23 17:23
     */
    private void recordNoDiscountFeeOrderDetail(List<PaymentOrderMchntFeeDiscountInfoBean> returnFeeOrderDetailList, PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail) {
        //设置实收手续费金额
        feeOrderDetail.setMchntFeeActual(MompAmountUtil.getThreeDecimal(feeOrderDetail.getMchntFeeReceivable()));
        //设置手续费优惠金额
        feeOrderDetail.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT);
        //添加到返回接口响应的列表
        returnFeeOrderDetailList.add(feeOrderDetail);

        rglog.error("机构<{}> 商户<{}>,无手续费优惠信息！", globalInstId, feeOrderDetail.getMchntNo());
    }

    /**
     * 检查商户是否可作为手续费优惠活动的新增商户
     * 返回true-成功
     * 返回false-失败，不可作为新商户享受免手续费优惠
     *
     * @param mcMchntFeeDiscountTransData
     * @param tmMcMchntFeeDiscountInfo    商户手续费减免类营销活动信息表
     * @param mchntExpandDate             商户入驻日期
     * @return boolean 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/7/29 15:38
     */
    private boolean checkNewMchntAvailability(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo, String mchntExpandDate, Boolean notDistinguishMiddleOfMonth) throws Exception {

        String mcNo = tmMcMchntFeeDiscountInfo.getMcNo();
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();

        int monthPeriod = Integer.parseInt(tmMcMchntFeeDiscountInfo.getNewMchntPeriod());

        String periodEndDate;
        //不区分15号之前之后时
        if (notDistinguishMiddleOfMonth) {
            periodEndDate = MompDateUtil.getFutureMonFirstDay(mchntExpandDate, monthPeriod);
        } else {
            periodEndDate = MompDateUtil.getFutureMonAddOneFirstDay(mchntExpandDate, monthPeriod);
        }
        String mcEndDate = tmMcMchntFeeDiscountInfo.getMcEndDate();
        String postponeFlag = tmMcMchntFeeDiscountInfo.getPostponeFlag();

        //如果免手续费到期时间在活动结束时间之前
        if (MompDateUtil.checkDateRange(periodEndDate, mcEndDate)) {
            tmMcMchntFeeDiscountInfo.setRemark1(periodEndDate);
        } else {
            //判断是否顺延，如果顺延，免费周期为顺延后的到期时间，保存到remark1中,后续使用此字段判断免费周期最长的
            if (CommonConstant.NEW_MCHNT_DISCOUNT_PROLONG.equals(postponeFlag)) {
                tmMcMchntFeeDiscountInfo.setRemark1(periodEndDate);
            } else {
                tmMcMchntFeeDiscountInfo.setRemark1(mcEndDate);
            }
        }

        if (MompDateUtil.checkDateRange(globalTxnDate, mcEndDate) && MompDateUtil.checkDateRange(globalTxnDate, periodEndDate)) {
            /* 当前交易日期同时在活动结束日期和最后的新商户统计周期内,可以优惠 */
            rglog.info("法人机构<{}>的商户手续费优惠活动<{}>可以对商户<{}>免手续费!", globalInstId, mcNo, mchntNo);
            return true;

        } else if (MompDateUtil.checkDateRange(globalTxnDate, periodEndDate)) {

            /* 当前交易日期在活动结束日期外,但在新商户统计周期内,需进一步判断 */
            if (CommonConstant.NEW_MCHNT_DISCOUNT_END.equals(postponeFlag)) {
                /* 活动结束后周期不自动顺延,即活动结束后就没有新商户免手续费的优惠 */
                rglog.error("法人机构<{}>的商户手续费优惠活动<{}>不支持新增商户周期顺延!该营销活动不可对商户<{}>免手续费!", globalInstId, mcNo, mchntNo);
                return false;

            } else if (CommonConstant.NEW_MCHNT_DISCOUNT_PROLONG.equals(postponeFlag)) {
                /* 商户手续费优惠营销活动新入驻商户活动结束后周期自动顺延 */
                rglog.info("法人机构<{}>的商户手续费优惠活动<{}>支持新增商户周期顺延!该营销活动可以对商户<{}>免手续费!", globalInstId, mcNo, mchntNo);
                return true;

            } else {
                rglog.error("法人机构<{}>的商户手续费优惠活动<{}>的新增商户周期顺延标志数据异常!该营销活动不可对商户<{}>免手续费!", globalInstId, mcNo, mchntNo);
                return false;
            }
        } else {
            rglog.error("商户<{}>在当前日期<{}>已不满足参加法人机构<{}>的商户手续费优惠活动<{}>并免手续费的条件!", mchntNo, globalTxnDate, globalInstId, mcNo);
            return false;
        }
    }

    /**
     * 确保任何情况下订单流水表都有记录
     *
     * @param xmlTreeUtil 内部XML树
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020-08-15 18:22
     */
    private void onlyRecordTxnOrderInfo(XmlTreeUtil xmlTreeUtil, ComboMchntFeeDiscountRequest comboMchntFeeDiscountRequest, boolean transactionFlag) throws Exception {
        if (procNormalStatus) {
            /* 如果交易状态是正常 */
            tmTxnOrder.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
            rglog.info("法人机构<{}>的流水号<{}>的订单号<{}>的订单处理成功——交易状态正常结束，无优惠信息登记订单流水表", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());
        } else {
            /* 如果交易状态是异常 */
            tmTxnOrder.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
            tmTxnOrder.setBizStatus(BizStatusEnum.PROCESS_FAILED.getBizStatusCode());
            rglog.info("法人机构<{}>的流水号<{}>的订单号<{}>的订单处理失败——交易状态异常结束，无优惠信息登记订单流水表", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());
        }

        /* 调用此函数的均为订单 无优惠 */
        tmTxnOrder.setOrderRemark(CommonConstant.DISCOUNT_FLAG_FALSE_CHECK_FLAG_FALSE);

        BigDecimal txnAmt = BigDecimal.ZERO;

        String txnAmtString = txnAmt.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
        tmTxnOrder.setTxnAmt(txnAmtString);
        tmTxnOrder.setSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        tmTxnOrder.setBankSubsidyAmt(CommonConstant.ZERO_AMOUNT);
        tmTxnOrder.setMchntSubsidyAmt(CommonConstant.ZERO_AMOUNT);

        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();

        if (transactionFlag) {
            /* 开启数据库事务 */
            String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
            String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
            if (null != corporation && !corporation.isEmpty()) {
                String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
                dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
            }
            DbsUtil dbsUtil = new DbsUtil(dbPoolName);
            dbsUtil.dbsBeginTransaction();

            int returnCode = tmTxnOrderMapper.insertSingleRecordIntoTMTxnOrder(tmTxnOrder);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                /* 更新失败 */
                rglog.error("插入法人机构<{}>的流水号<{}>的订单号<{}>的订单数据失败! RETURN_CODE=<{}>", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId(), returnCode);
                dbsUtil.dbsEndTransaction(false);
            } else {
                rglog.info("插入法人机构<{}>的流水号<{}>的订单号<{}>的订单数据成功!", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());
                dbsUtil.dbsEndTransaction(true);
            }
        } else {
            int returnCode = tmTxnOrderMapper.insertSingleRecordIntoTMTxnOrder(tmTxnOrder);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                /* 更新失败 */
                rglog.error("插入法人机构<{}>的流水号<{}>的订单号<{}>的订单数据失败! RETURN_CODE=<{}>", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId(), returnCode);
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            } else {
                rglog.info("插入法人机构<{}>的流水号<{}>的订单号<{}>的订单数据成功!", tmTxnOrder.getInstId(), tmTxnOrder.getFrontSeqNum(), tmTxnOrder.getOrderId());
            }
        }
    }

    /**
     * 查询商户是否已经到了退出条件，并更新数据库
     *
     * @param mcMchntFeeDiscountTransData
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020-08-15 18:22
     */
    private void checkExitFlagAndUpdateTMStatMfdCriteria(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {

        String exit_txn_qty_flag = mcMchntFeeDiscountTransData.getExitTxnQtyFlag();
        String exit_txn_amt_flag = mcMchntFeeDiscountTransData.getExitTxnAmtFlag();
        String exit_discount_flag = mcMchntFeeDiscountTransData.getExitDiscountFlag();

        //商户优惠交易笔数退出标志exit_txn_qty_flag、商户优惠交易金额退出标志exit_txn_amt_flag或商户优惠额退出标志exit_discount_flag
        if (CommonConstant.ONE_COMMON_CONSTANT.equals(exit_txn_qty_flag) ||
                CommonConstant.ONE_COMMON_CONSTANT.equals(exit_txn_amt_flag) ||
                CommonConstant.ONE_COMMON_CONSTANT.equals(exit_discount_flag)) {
            rglog.info("机构<{}> 商户<{}> 营销活动编号<{}> 退出标志exit_txn_qty_flag:<{}>,exit_txn_amt_flag:<{}>,exit_discount_flag:<{}>！",
                    mcMchntFeeDiscountTransData.getInstId(), mcMchntFeeDiscountTransData.getMchntNo(), mcMchntFeeDiscountTransData.getMcNo(), exit_txn_qty_flag, exit_txn_amt_flag, exit_discount_flag);
            //如果达到退出条件，则更新手续费减免达标数据统计表 优惠退出状态exit_discount_status 为1已退出优惠
            TMStatMfdCriteria updateTMStatMfdCriteria = new TMStatMfdCriteria();
            updateTMStatMfdCriteria.setInstId(mcMchntFeeDiscountTransData.getInstId());
            updateTMStatMfdCriteria.setMcNo(mcMchntFeeDiscountTransData.getMcNo());
            updateTMStatMfdCriteria.setMchntNo(mcMchntFeeDiscountTransData.getMchntNo());
            updateTMStatMfdCriteria.setRecIndex(mcMchntFeeDiscountTransData.getRecIndex());
            updateTMStatMfdCriteria.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            updateTMStatMfdCriteria.setUpdateTime(globalTimeStamp);
            updateTMStatMfdCriteria.setExitDiscountStatus(CommonConstant.MC_EXIT_FLAG);
            //更新营销活动手续费减免达标数据统计表优惠退出标志exit_discount_status置为1-已退出
            TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
            int updateReturnCode = tmStatMfdCriteriaMapper.updateTMstatMfdCriteriaByPrimaryKey(updateTMStatMfdCriteria);
            if (updateReturnCode != 0) {
                rglog.error("机构<{}> 商户<{}> 营销活动编号<{}> 根据主键更新营销活动手续费减免达标数据统计表失败！",
                        mcMchntFeeDiscountTransData.getInstId(), mcMchntFeeDiscountTransData.getMchntNo(), mcMchntFeeDiscountTransData.getMcNo());
                throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
            }
        }
    }

    /**
     * 使用主键取手续费减免活动商户统计表单条数据
     *
     * @param instId
     * @param mcNo
     * @param ruleIndex
     * @param mchntNo
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt
     * @throws Exception
     * @author liujinan
     * @date 2020/9/15
     */
    private TMStatMfdMchnt selectNowPeriodDateTMStatMfdMchnt(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectNowPeriodDateTMStatMfdMchnt(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 手续费减免活动商户统计数据(商户维度)赋值
     *
     * @param tmStatMfdMchnt 手续费减免活动商户统计表
     * @author liujinan
     * @since 2020/9/24 11:23
     */
    private void copyMchntFeeDiscountMchntStat9999Data(TMStatMfdMchnt tmStatMfdMchnt, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 总预算累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntTotalQtyAcc9999(tmStatMfdMchnt.getTotalQtyAcc());
        /* 总预算累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntTotalAmtAcc9999(tmStatMfdMchnt.getTotalAmtAcc());
        /* 总预算累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntTxnQtyAcc9999(tmStatMfdMchnt.getTxnQtyAcc());
        /* 总预算累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntTxnAmtAcc9999(tmStatMfdMchnt.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户单日统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfdMchntDay           手续费减免活动商户单日统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/9/25 11:22
     */
    private void copyMchntFeeDiscountMchntDayZeroStatData(TMStatMfdMchntDay tmStatMfdMchntDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户单日统计数据-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTotalQtyAccZero(tmStatMfdMchntDay.getTotalQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntDayTotalAmtAccZero(tmStatMfdMchntDay.getTotalAmtAcc());
        /* 手续费减免活动商户单日统计数据-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTxnQtyAccZero(tmStatMfdMchntDay.getTxnQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntDayTxnAmtAccZero(tmStatMfdMchntDay.getTxnAmtAcc());
    }

    /**
     * 计算新增商户优惠的手续费
     *
     * @return CommonConstant.ZERO:成功，流程继续  1:本次结束，继续下一次
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/10/16
     */
    private int getNewMchntFeeDiscount(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail) throws Exception {

        /* 获取交易额度上限 */
        rglog.info("机构<{}> 商户<{}> 营销活动<{}> 获取各维度统计数据开始...!", globalInstId, mcMchntFeeDiscountTransData.getMchntNo(), mcMchntFeeDiscountTransData.getMcNo());
        int returnCode = fetchNewMchntFeeDiscountMcQuotaData(mcMchntFeeDiscountTransData);
        if (CommonConstant.ONE == returnCode) {
            rglog.info("获取机构<{}>的营销活动<{}>各维度限额和额度失败,本营销活动不予优惠!", globalInstId, mcMchntFeeDiscountTransData.getMcNo());
            return CommonConstant.ONE;
        }

        /* 判断交易额度上限 */
        rglog.info("机构<{}> 商户<{}> 营销活动<{}> 判断交易额度限制开始...!", globalInstId, mcMchntFeeDiscountTransData.getMchntNo(), mcMchntFeeDiscountTransData.getMcNo());
        returnCode = checkNewMchntFeeDiscountLimits(mcMchntFeeDiscountTransData, feeOrderDetail);
        if (CommonConstant.ONE == returnCode) {
            rglog.info("机构<{}>的营销活动<{}>判断各维度限额和额度未通过,本营销活动不予优惠!", globalInstId, mcMchntFeeDiscountTransData.getMcNo());
            return CommonConstant.ONE;
        }

        //设置实收手续费金额
        feeOrderDetail.setMchntFeeActual(mcMchntFeeDiscountTransData.getMchntFeeActual());
        //设置手续费优惠金额
        feeOrderDetail.setMchntFeeDiscount(mcMchntFeeDiscountTransData.getMchntFeeDiscount());

        rglog.info("通过限额检查后计算出的机构<{}>的商户的<{}>的商户手续费优惠营销活动<{}>的减免金额<{}>,实收手续费<{}>", globalInstId, mcMchntFeeDiscountTransData.getMchntNo(),
                mcMchntFeeDiscountTransData.getMcNo(), mcMchntFeeDiscountTransData.getMchntFeeDiscount(), mcMchntFeeDiscountTransData.getMchntFeeActual());

        BigDecimal totalSubsidy = new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeDiscount()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //本笔手续费订单金额(接口上送的金额)
        BigDecimal mchntSettleAmt = new BigDecimal(feeOrderDetail.getMchntSettleAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //本笔手续费优惠订单金额
        BigDecimal mchntFeeDiscountTransAmt = new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeDiscountTransAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        if (CommonConstant.ZERO == BigDecimal.ZERO.compareTo(totalSubsidy) && CommonConstant.ZERO == mchntSettleAmt.compareTo(mchntFeeDiscountTransAmt)) {
            /* 优惠金额为0,不优惠商户手续费 */
            rglog.info("最终通过计算出的商户优惠手续费为 0,不优惠!!!");
            return CommonConstant.ONE;
        }
        return CommonConstant.ZERO;
    }

    /**
     * 商户手续费优惠类营销活动交易限额处理
     *
     * @param mcMchntFeeDiscountTransData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/10/16 17:36
     */
    private int checkNewMchntFeeDiscountLimits(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail) throws Exception {

        String instId = mcMchntFeeDiscountTransData.getInstId();
        String mcNo = mcMchntFeeDiscountTransData.getMcNo();
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();
        String newmrctFreeLmtTyp = mcMchntFeeDiscountTransData.getNewmrctFreeLmtTyp();

        //本笔手续费优惠订单金额
        BigDecimal orderAmt = new BigDecimal(feeOrderDetail.getMchntSettleAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户统计-累计交易金额
        BigDecimal txnAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTxnAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户单日统计数据 具体规则-累计交易金额
        BigDecimal txnAmtAccDay = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTxnAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户统计-累计优惠手续费金额
        BigDecimal mchntTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //手续费减免活动商户单日统计数据 具体规则-累计优惠手续费金额
        BigDecimal mchntTotalAmtAccDay = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalAmtAcc()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        //本笔应收手续费
        BigDecimal mchntFeeReceivable = new BigDecimal(feeOrderDetail.getMchntFeeReceivable());
        //本笔优惠手续费 新商户手续费全免，优惠=应收
        BigDecimal mchntFeeDiscount = new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeDiscount());

        BigDecimal discountLimit;
        /* 判断新商户优惠上限是否超限 */
        if (null != mcMchntFeeDiscountTransData.getMrctDisUpLmtVal() && !"".equals(mcMchntFeeDiscountTransData.getMrctDisUpLmtVal())) {
            discountLimit = new BigDecimal(mcMchntFeeDiscountTransData.getMrctDisUpLmtVal()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        } else {
            discountLimit = new BigDecimal(mcMchntFeeDiscountTransData.getNewMchntAmountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        }
        //如果新商户上限为免交易金额，为空时默认为免交易金额
        if (null == newmrctFreeLmtTyp || CommonConstant.ZERO_COMMON_CONSTANT.equals(newmrctFreeLmtTyp)) {
            //本笔交易金额 + 周期统计累计优惠交易金额 + 单日统计累计优惠交易金额
            BigDecimal totalDiscount = orderAmt.add(txnAmtAcc).add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            rglog.info("新商户周期内优惠上限<{}>,加本笔优惠交易金额<{}>", discountLimit, totalDiscount);
            if (CommonConstant.ZERO <= discountLimit.compareTo(totalDiscount)) {
                rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>规则<{}>加本次已优惠<{}>优惠上限<{}>校验通过，未超规则限额!流程继续！", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), totalDiscount, discountLimit);
            } else {
                BigDecimal historyTotalDiscount = txnAmtAcc.add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                if (CommonConstant.ZERO < discountLimit.compareTo(historyTotalDiscount)) {
                    BigDecimal remainderDiscountAmt = discountLimit.subtract(historyTotalDiscount).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                    rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>规则<{}>不加本次已优惠<{}>优惠上限<{}> 有剩余可优惠额度<{}>，开始重新计算手续费！", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), historyTotalDiscount, discountLimit, remainderDiscountAmt);
                    //重新计算手续费
                    boolean recalculateMchntFee = recalculateMchntFee(mcMchntFeeDiscountTransData, orderAmt, remainderDiscountAmt, feeOrderDetail, CommonConstant.ONE_COMMON_CONSTANT);
                    if (recalculateMchntFee) {
                        //商户优惠交易金额 */
                        mcMchntFeeDiscountTransData.setMchntFeeDiscountTransAmt(remainderDiscountAmt.toString());
                        //手续费优惠值可能经过了重新手续费优惠计算有变化，所以重新赋值
                        mchntFeeDiscount = new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeDiscount());
                    } else {
                        rglog.info("商户<{}> 重新计算手续费优惠失败，无手续费优惠!!!", mchntNo);
                        return CommonConstant.ONE;
                    }
                } else {
                    /* 限额小于累计优惠金额(当前包含本笔优惠金额),不可以优惠 */
                    rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}>周期内新商户加本次已优惠<{}> 优惠上限<{}>，已超新商户优惠交易限额!", instId, mcNo, totalDiscount, discountLimit);
                    return CommonConstant.ONE;
                }
            }
        } else {
            //如果新商户上限为免手续费金额
            //本笔优惠手续费金额 + 周期统计累计优惠手续费金额 + 单日统计累计优惠手续费金额
            BigDecimal totalMchntFeeDiscount = mchntFeeDiscount.add(mchntTotalAmtAcc).add(mchntTotalAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            rglog.info("新商户周期内优惠上限<{}>,加本笔优惠手续费金额<{}>", discountLimit, totalMchntFeeDiscount);

            if (CommonConstant.ZERO <= discountLimit.compareTo(totalMchntFeeDiscount)) {
                rglog.info("法人机构<{}> 手续费优惠营销活动<{}> 规则<{}> 加本次已优惠<{}>优惠上限<{}>校验通过，未超规则限额!流程继续！", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), totalMchntFeeDiscount, discountLimit);
            } else {
                if (CommonConstant.ZERO >= discountLimit.compareTo(totalMchntFeeDiscount.subtract(mchntFeeDiscount))) {
                    rglog.info("商户<{}> 营销活动<{}> 不加本笔已累计优惠手续费金额<{}> 超出规则限制 <{}>,不予优惠！！！", mchntNo, mcNo, totalMchntFeeDiscount.subtract(mchntFeeDiscount), discountLimit);
                    return CommonConstant.ONE;
                } else {
                    mchntFeeDiscount = discountLimit.subtract(totalMchntFeeDiscount.subtract(mchntFeeDiscount));
                    rglog.info("商户<{}> 营销活动<{}> 不加本笔优惠手续费金额<{}> 未超过规则限制<{}>,仅可优惠剩余额度<{}>！！！", mchntNo, mcNo, totalMchntFeeDiscount.subtract(mchntFeeDiscount), discountLimit, mchntFeeDiscount);
                }
            }
        }

        //总预算 营销活动预算资金
        BigDecimal budget = new BigDecimal(mcMchntFeeDiscountTransData.getBudget());
        if (budget.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
            //总预算累计消耗金额  活动统计表+单日统计表+本笔交易中明细的汇总+本笔本商户的明细
            BigDecimal mcTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMcTotalAmtAcc()).add(mchntFeeDiscount);
            if (CommonConstant.ZERO <= budget.compareTo(mcTotalAmtAcc)) {
                rglog.info("商户<{}> 营销活动<{}> 加上本笔累计优惠金额<{}> 未超出总预算<{}>,给予优惠！！！", mchntNo, mcNo, mcTotalAmtAcc, budget);
            } else {
                rglog.info("加上本笔手续费优惠金额交易超出预算资金，继续判断不加本笔手续费优惠金额是否超出预算资金");
                if (CommonConstant.ZERO >= budget.compareTo(mcTotalAmtAcc.subtract(mchntFeeDiscount))) {
                    rglog.info("商户<{}> 营销活动<{}> 不加本笔已累计优惠金额<{}> 超出总预算<{}>,不予优惠！！！", mchntNo, mcNo, mcTotalAmtAcc.subtract(mchntFeeDiscount), budget);
                    return CommonConstant.ONE;
                } else {
                    rglog.info("商户<{}> 营销活动<{}> 不加本笔优惠金额<{}> 未超过总预算<{}>,仅可优惠剩余额度<{}>！！！", mchntNo, mcNo, mcTotalAmtAcc.subtract(mchntFeeDiscount), budget, budget.subtract(mcTotalAmtAcc.subtract(mchntFeeDiscount)));
                    mchntFeeDiscount = budget.subtract(mcTotalAmtAcc.subtract(mchntFeeDiscount));
                }
            }
        } else {
            rglog.info("默认预算资金无上限,不判断是否超出预算资金");
        }

        //重新给优惠手续费金额赋值
        mcMchntFeeDiscountTransData.setMchntFeeDiscount(mchntFeeDiscount.toString());
        //重新给实收手续费赋值
        mcMchntFeeDiscountTransData.setMchntFeeActual(mchntFeeReceivable.subtract(mchntFeeDiscount).toString());

        return CommonConstant.ZERO;
    }

    /**
     * 手续费减免活动统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfd    手续费减免活动统计表
     * @param tmStatMfdDay 手续费减免活动单日统计表
     * @author JL Pang
     * @since 2020/10/18 11:22
     */
    private void copyMchntFeeDiscountZeroStatData(TMStatMfd tmStatMfd, TMStatMfdDay tmStatMfdDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {
//        BigDecimal thisOrderTotalAmtAcc = BigDecimal.ZERO;
//        List<TMStatMfdDay> statMfdThisOrderList = statMfdDayList.stream().filter(item ->item.getInstId().equals(mcMchntFeeDiscountTransData.getInstId()) && item.getMcNo().equals(mcMchntFeeDiscountTransData.getMcNo())).collect(Collectors.toList());
//        if(statMfdThisOrderList.size()>0){
//            //本笔流水中交易额,包含本笔明细中的
//            TMStatMfdDay statMfdThisOrder = statMfdThisOrderList.get(0);
//            thisOrderTotalAmtAcc = new BigDecimal(statMfdThisOrder.getTotalAmtAcc());
//        }

        /* 手续费减免活动统计数据-总预算消耗金额 加本订单中参加相同活动的商户消耗预算，不加本明细手续费*/
        mcMchntFeeDiscountTransData.setMcTotalAmtAcc(new BigDecimal(tmStatMfd.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).toString());

    }

    /**
     * 检查 手续费订单明细 金额字段不能为负数
     *
     * @param feeOrderDetail
     * @throws Exception
     */
    private void checkFeeOrderDetailFieldHasNegativeNumber(PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail) throws Exception {
        /*订单金额*/
        if (!StringUtil.isNullorEmpty(feeOrderDetail.getOrderAmt()) && new BigDecimal(feeOrderDetail.getOrderAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*商户清算金额*/
        if (!StringUtil.isNullorEmpty(feeOrderDetail.getMchntSettleAmt()) && new BigDecimal(feeOrderDetail.getMchntSettleAmt()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /* 商户应收手续费金额 */
        if (!StringUtil.isNullorEmpty(feeOrderDetail.getMchntFeeReceivable()) && new BigDecimal(feeOrderDetail.getMchntFeeReceivable()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*手续费优惠金额*/
        if (!StringUtil.isNullorEmpty(feeOrderDetail.getMchntFeeDiscount()) && new BigDecimal(feeOrderDetail.getMchntFeeDiscount()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
        /*实收手续费金额*/
        if (!StringUtil.isNullorEmpty(feeOrderDetail.getMchntFeeActual()) && new BigDecimal(feeOrderDetail.getMchntFeeActual()).compareTo(zero) < 0) {
            throw new BizException(RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespCode(), RespCodeEnum.FIELD_HAS_NEGATIVE_NUMBER.getRespDesc());
        }
    }

    /**
     * 取新商户手续费优惠类营销活动各维度统计数据
     *
     * @param mcMchntFeeDiscountTransData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/10/19 10:22
     */
    private int fetchNewMchntFeeDiscountMcQuotaData(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {

        //规则维度批量处理状态
        int batchStatus_stat_mfd = CommonConstant.FLAG_NOT_SET;
        int batchStatus_stat_mfd_mchnt = CommonConstant.FLAG_NOT_SET;
        String instId = mcMchntFeeDiscountTransData.getInstId();
        String mcNo = mcMchntFeeDiscountTransData.getMcNo();
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();
        String transDate = mcMchntFeeDiscountTransData.getTransDate();
        String periodStartDate = mcMchntFeeDiscountTransData.getPeriodStartDate();
        String periodEndDate = mcMchntFeeDiscountTransData.getPeriodEndDate();
        String mcStartDate = mcMchntFeeDiscountTransData.getMcStartDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);
        String ruleIndex = mcMchntFeeDiscountTransData.getRuleIndex();
        String mfdCriteriaCreateTimeTmp = mcMchntFeeDiscountTransData.getMfdCriteriaCreateTime();
        String mfdCriteriaCreateTime = mfdCriteriaCreateTimeTmp.substring(0, 4) + mfdCriteriaCreateTimeTmp.substring(5, 7) + mfdCriteriaCreateTimeTmp.substring(8, 10);

        /*------------------------------------------------查询营销活动商户维度汇总数据------------------------------------*/

        /* 查询商户手续费优惠营销活动商户统计表数据  查询具体规则维度的统计数值 新增商户的这个值应该为0*/
        TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
        if (null == tmStatMfdMchnt) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt = new TMStatMfdMchnt();
            tmStatMfdMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据 新增商户的这个值应该为0*/
        TMStatMfdMchntDay tmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, transDate);
        if (null == tmStatMfdMchntDay) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
            tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "FeeMchnt" + instId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = periodStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDay) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
                newtmStatMfdMchntDay = new TMStatMfdMchntDay();
                newtmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, periodStartDate) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，不需要累加到商户统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到商户统计表!", batchDate);
                copyMchntStatMfdData(tmStatMfdMchnt, newtmStatMfdMchntDay);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        copyMchntFeeDiscountMchntStatData(tmStatMfdMchnt, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayStatData(tmStatMfdMchntDay, mcMchntFeeDiscountTransData);

        /*------------------------------------------------查询营销活动维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        statPrimaryKey = "Fee" + instId + "_" + mcNo;
        tmStatBak = selectTMStatBakByStatPrimaryKey(instId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        TMStatMfd tmStatMfd = selectMchntFeeDiscountStatisticsByPK(instId, mcNo, ruleIndex);
        if (null == tmStatMfd) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfd = new TMStatMfd();
            tmStatMfd.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay1 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, batchDate);
            if (null == tmStatMfdDay1) {
                rglog.info("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
                tmStatMfdDay1 = new TMStatMfdDay();
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            } else {
                rglog.info("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询成功!", instId, mcNo, ruleIndex);
            }
            copyStatMfdData(tmStatMfd, tmStatMfdDay1);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
        TMStatMfdDay tmStatMfdDay = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, transDate);
        if (null == tmStatMfdDay) {
            rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
            tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        //判断本笔交易明细中是否有参加相同活动的商户
        List<TMStatMfdDay> statMfdThisOrderList = statMfdDayList.stream().filter(item -> item.getInstId().equals(instId) && item.getMcNo().equals(mcNo)).collect(Collectors.toList());
        //存在本笔交易同一活动数据
        if (statMfdThisOrderList.size() > 0) {
            //全局变量手续费营销活动单日统计表数据更新已优惠金额
            TMStatMfdDay tmStatMfdThisOrder = statMfdThisOrderList.get(0);
            BigDecimal totalAmtAccThisOrder = new BigDecimal(tmStatMfdThisOrder.getTotalAmtAcc());
            //把本订单使用相同活动的优惠金额累加
            statMfdDayList.stream().filter(item -> item.getInstId().equals(instId) && item.getMcNo().equals(mcNo)).collect(Collectors.toList()).get(0).setTotalAmtAcc(totalAmtAccThisOrder.add(new BigDecimal((mcMchntFeeDiscountTransData.getMchntFeeDiscount()))).toString());
        } else {
            //如果不存在 将子订单set
            TMStatMfdDay tmStatMfdThisOrder = new TMStatMfdDay();
            tmStatMfdThisOrder.setTotalAmtAcc(mcMchntFeeDiscountTransData.getMchntFeeDiscount());
            tmStatMfdThisOrder.setInstId(instId);
            tmStatMfdThisOrder.setMcNo(mcNo);
            statMfdDayList.add(tmStatMfdThisOrder);
        }
        //将累计优惠手续费金额赋值
        copyMchntFeeDiscountZeroStatData(tmStatMfd, tmStatMfdDay, mcMchntFeeDiscountTransData);

        return CommonConstant.ZERO;
    }

    /**
     * 商户手续费优惠活动查询营销活动商户信息
     *
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntInfo 商户基本信息表T_B_MCHNT_BASE_INFO
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2021/2/26 10:13
     */
    private List<TMMcMchntInfo> selectMcMchntInfoListByMcNo(String instId, String mcNo, String mchntType) throws Exception {

        TMMcMchntInfo mcMchntInfo = new TMMcMchntInfo();
        mcMchntInfo.setInstId(instId);
        mcMchntInfo.setMcNo(mcNo);
        mcMchntInfo.setMchntType(mchntType);

        McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
        return mcMchntInfoMapper.selectMcMchntInfoListByMcNo(instId, mcNo, mchntType);
    }

    /**
     * 判断活动是否区分商户性质的才能参加
     *
     * @author liujinan
     * @date 2021/3/21 10:13
     */
    private void JudgeMcDiscriminateMchntNature(List<TMMcMchntFeeDiscountInfo> inputTmMcMchntFeeDiscountInfo, List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {
        if (CommonConstant.ZERO < inputTmMcMchntFeeDiscountInfo.size()) {
            if (CommonConstant.INST_ID_815.equals(globalInstId)) {
                JudgeMcDiscriminateMchntNature815(inputTmMcMchntFeeDiscountInfo, tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, mcMchntFeeDiscountTransData);
            } else {
                JudgeMcDiscriminateMchntNatureOthers(inputTmMcMchntFeeDiscountInfo, tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, mcMchntFeeDiscountTransData);
            }
        } else {
            rglog.info("法人机构<{}>的商户<{}>未找到适合的支持新增商户的营销活动,该商户无法享受任何商户手续费优惠活动!", globalInstId, mcMchntFeeDiscountTransData.getMchntNo());
        }
    }

    /**
     * 判断活动是否区分商户性质的才能参加--815济宁行处理流程
     *
     * @author liujinan
     * @date 2021/5/12 10:13
     */
    private void JudgeMcDiscriminateMchntNature815(List<TMMcMchntFeeDiscountInfo> inputTmMcMchntFeeDiscountInfo, List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {
        //当前商户号
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();
        //当前商户的性质 01-小微商户 02-个体工商户 03-企业 04-党政 05-机关及事业单位 99-其他组织
        String mchntNature = mcMchntFeeDiscountTransData.getMchntNature();
        rglog.info("当前商户<{}> 企业性质为<{}> 01-小微商户 02-个体工商户 03-企业 04-党政 05-机关及事业单位 99-其他组织", mchntNo, mchntNature);

        //查询商户的结算账户
        rglog.info("查询商户<{}> 的结算账户信息!", mcMchntFeeDiscountTransData.getMchntNo());
        /*商户结算信息正式表*/
        McMchntAcctInfoMapper mcMchntAcctInfoMapper = new McMchntAcctInfoMapperImpl();
        MchntAcctInfo mchntAcctInfo = mcMchntAcctInfoMapper.selectMchntAcctInfoByPrimaryKey(globalInstId, mchntNo, "*", FundTypeEnum.SETTLE_TYPE.getFundCode());

        /* 判断活动是否区分商户性质参加，如果区分，则判断当前商户是否符合条件 */
        for (TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo : inputTmMcMchntFeeDiscountInfo) {
            //当前活动支持的商户类型
            String avySprtMrctTypString = tmMcMchntFeeDiscountInfo.getavySprtMrctTyp();
            if (null == avySprtMrctTypString ||
                    CommonConstant.EMPTY_STRING.equals(avySprtMrctTypString) ||
                    CommonConstant.SUPPORT_ALLTYPES_MCHNT.equals(avySprtMrctTypString)) {
                rglog.info("营销活动<{}> 支持所有类型的商户参加,无需校验当前商户的性质", tmMcMchntFeeDiscountInfo.getMcNo());
                tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
            } else {
                //当前活动支持的商户性质 小微商户|个体工商户|企业|党政|机关及事业单位|其他组织
                String[] avySprtMrctTyp = avySprtMrctTypString.split(CommonConstant.VERTICAL_LINE);
                if (CommonConstant.SIX != avySprtMrctTyp.length) {
                    rglog.error("营销活动<{}> 配置的支持参加的商户类型异常,商户无法参加本活动！", tmMcMchntFeeDiscountInfo.getMcNo());
                    continue;
                }

                String settleAcctType = "";
                if (null != mchntAcctInfo) {
                    //结算账户类型
                    settleAcctType = mchntAcctInfo.getSettleAcctType();
                    if (AcctTypeEnum.OWN_CORPORATE_ACCOUNT.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OTHER_CORPORATE_ACCOUNT.getAcctType().equals(settleAcctType)) {
                        rglog.info("当前商户<{}> 结算账户类型<{}> 结算账户为对公户，对公户需要参与针对企业商户的营销活动，判断当前营销活动是否满足!", mchntNo, settleAcctType);
                        if (!CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[2])) {
                            rglog.error("当前活动<{}> 不支持企业类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                        } else {
                            rglog.info("当前活动<{}> 支持企业类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        }
                    } else if (AcctTypeEnum.OWN_DEBIT.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OWN_CREDIT.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OWN_BANK_BOOK.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OTHER_DEBIT.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OTHER_CREDIT.getAcctType().equals(settleAcctType) ||
                            AcctTypeEnum.OTHER_BANK_BOOK.getAcctType().equals(settleAcctType)) {
                        rglog.info("当前商户<{}> 结算账户类型<{}> 结算账户为对私户，小微商户参与小微商户的活动，其他类型的商户参与个体商户的营销活动!", mchntNo, settleAcctType);
                        if ("01".equals(mchntNature)) {
                            //判断当前商户是否支持小微企业的营销活动+
                            if (!CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[0])) {
                                rglog.error("当前活动<{}> 不支持小微类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                            } else {
                                rglog.info("当前活动<{}> 支持小微类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                                tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                            }
                        } else {
                            //判断当前商户是否支持个体的营销活动
                            if (!CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[1])) {
                                rglog.error("当前活动<{}> 不支持个体类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                            } else {
                                rglog.info("当前活动<{}> 支持个体类型商户参与活动!", tmMcMchntFeeDiscountInfo.getMcNo());
                                tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                            }
                        }
                    } else {
                        rglog.error("商户<{}> 结算账户类型<{}> 不是对公户也不是对私户，不能参加当前活动!", tmMcMchntFeeDiscountInfo.getMcNo(), settleAcctType);
                    }
                } else {
                    rglog.error("商户<{}> 结算账户信息查询异常，无法判断是否能够参与营销活动!", mcMchntFeeDiscountTransData.getMchntNo());
                }
            }
        }
        rglog.info("判断各活动是否区分商户性质完成，流程继续！");
    }

    /**
     * 判断活动是否区分商户性质的才能参加--通用处理流程
     *
     * @author liujinan
     * @date 2021/5/12 10:13
     */
    private void JudgeMcDiscriminateMchntNatureOthers(List<TMMcMchntFeeDiscountInfo> inputTmMcMchntFeeDiscountInfo, List<TMMcMchntFeeDiscountInfo> tmMcMchntFeeDiscountInfoAfterJudgeMchntNature, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {
        //当前商户号
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();
        //当前商户的性质 01-小微商户 02-个体工商户 03-企业 04-党政 05-机关及事业单位 99-其他组织
        String mchntNature = mcMchntFeeDiscountTransData.getMchntNature();
        rglog.info("当前商户<{}> 企业性质为<{}> 01-小微商户 02-个体工商户 03-企业 04-党政 05-机关及事业单位 99-其他组织", mchntNo, mchntNature);

        /* 判断活动是否区分商户性质参加，如果区分，则判断当前商户是否符合条件 */
        for (TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo : inputTmMcMchntFeeDiscountInfo) {
            //当前活动支持的商户类型
            String avySprtMrctTypString = tmMcMchntFeeDiscountInfo.getavySprtMrctTyp();
            if (null == avySprtMrctTypString ||
                    CommonConstant.EMPTY_STRING.equals(avySprtMrctTypString) ||
                    CommonConstant.SUPPORT_ALLTYPES_MCHNT.equals(avySprtMrctTypString)) {
                rglog.info("营销活动<{}> 支持所有类型的商户参加,无需校验当前商户的性质", tmMcMchntFeeDiscountInfo.getMcNo());
                tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
            } else {
                //当前活动支持的商户性质 小微商户|个体工商户|企业|党政|机关及事业单位|其他组织
                String[] avySprtMrctTyp = avySprtMrctTypString.split(CommonConstant.VERTICAL_LINE);

                if (CommonConstant.SIX != avySprtMrctTyp.length) {
                    rglog.error("营销活动<{}> 配置的支持参加的商户类型异常,商户无法参加本活动！", tmMcMchntFeeDiscountInfo.getMcNo());
                    continue;
                }

                switch (mchntNature) {
                    case "01":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[0])) {
                            rglog.info("营销活动<{}>限定商户性质,允许小微商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许小微商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    case "02":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[1])) {
                            rglog.info("营销活动<{}>限定商户性质,允许个体工商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许个体工商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    case "03":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[2])) {
                            rglog.info("营销活动<{}>限定商户性质,允许企业商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许企业商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    case "04":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[3])) {
                            rglog.info("营销活动<{}>限定商户性质,允许党政商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许党政商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    case "05":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[4])) {
                            rglog.info("营销活动<{}>限定商户性质,允许机关及事业单位商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许机关及事业单位商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    case "99":
                        if (CommonConstant.ONE_COMMON_CONSTANT.equals(avySprtMrctTyp[5])) {
                            rglog.info("营销活动<{}>限定商户性质,允许其他组织商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                            tmMcMchntFeeDiscountInfoAfterJudgeMchntNature.add(tmMcMchntFeeDiscountInfo);
                        } else {
                            rglog.info("营销活动<{}>限定商户性质,不允许其他组织商户参与", tmMcMchntFeeDiscountInfo.getMcNo());
                        }
                        break;
                    default:
                        rglog.error("当前活动<{}>限定商户性质，但当前商户的性质异常 mchntNature: <{}>", tmMcMchntFeeDiscountInfo.getMcNo(), mchntNature);
                        break;
                }
            }
        }
        rglog.info("判断各活动是否区分商户性质完成，流程继续！");
    }

    /**
     * 校验商户是否重复入网商户
     *
     * @param mchntNo         商户编号
     * @param mchntExpandTime 商户入驻时间
     * @return
     * @throws Exception
     * @author liujinan
     * @since 2021/5/28 09:06
     */
    private boolean checkMchntRepeatFlag(String mchntNo, String mchntExpandTime) throws Exception {
        boolean repeatFlag = false;
        /* 东营行校验重复入网 */
        if (INST_ID_DY.equals(globalInstId)) {
            rglog.info("根据机构号<{}>商户<{}>入驻时间<{}>校验是否存在注销后一年内重复入网商户", globalInstId, mchntNo, mchntExpandTime);
            //格式化商户入驻日期
            String mchntExpandDate = mchntExpandTime.replaceAll("-", "").substring(0, 8);
            //获取一年前日期
            String lastYearDate = MompDateUtil.getFutureMonDay(mchntExpandDate, -12);
            //获取商户基本信息,可能存在多个结算账号
            List<TBMchntSignInfo> tbMchntSignList = selectMchntSignInfoByPrimaryPK(globalInstId, mchntNo);
            rglog.info("查询商户<{}>签约信息size=<{}>", mchntNo, tbMchntSignList.size());
            for (TBMchntSignInfo tbMchntSignInfo : tbMchntSignList) {
                //查询历史签约商户号
                List<TBMchntSignInfo> signList = selectRepeatMchntBySignInfoForDY(globalInstId, mchntNo, tbMchntSignInfo.getArtifCertNo(), tbMchntSignInfo.getLicenceCode(), tbMchntSignInfo.getSettleAcctNo());
                if (signList != null && !signList.isEmpty()) {
                    rglog.info("查询商户<{}>证件信息历史入驻信息size=<{}>", mchntNo, signList.size());
                    for (TBMchntSignInfo signInfo : signList) {
                        String cancelMchntNo = signInfo.getMchntNo();
                        if (!cancelMchntNo.equals(mchntNo)) {
                            String expandTime = signInfo.getExpandTime();
                            String lastAuditTime = signInfo.getLastAuditTime();
                            rglog.info("商户<{}>入驻时间(一年前)<{}>,检查注销商户[{}],入驻时间为[{}],注销时间为[{}],", mchntNo, lastYearDate, cancelMchntNo, expandTime, lastAuditTime);
                            if (!StringUtil.isNullorEmpty(lastAuditTime)) {
                                //格式化商户注销日期
                                String cancelDate = DateUtil.dateStringFormatConvert(lastAuditTime.substring(0, 10), "yyyy-MM-dd", "yyyyMMdd");
                                //判断注销商户注销后是否一年内入网
                                if (DateUtil.compareDate(cancelDate, lastYearDate) > 0) {
                                    //查询商户营销统计商户表累计优惠额度
                                    TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeTotalAmtMchntStatistics(globalInstId, cancelMchntNo);
                                    if (tmStatMfdMchnt != null) {
                                        String totalAmtAcc = tmStatMfdMchnt.getTotalAmtAcc();
                                        //超过额度，判定为重复入网
                                        if (!StringUtil.isNullorEmpty(totalAmtAcc) && AmountUtil.compare(totalAmtAcc, DISCOUNT_AMOUNT) == 1) {
                                            repeatFlag = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return repeatFlag;
    }

    /**
     * 使用商户编号从内管商户签约信息表查询商户签约信息
     *
     * @param globalInstId 法人机构号
     * @param mchntNo      商户编号
     * @return cc.rengu.igas.momp.common.entity.TBMchntBaseInfo 商户基本信息表T_B_MCHNT_BASE_INFO
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2021/5/28 09:06
     */
    private List<TBMchntSignInfo> selectMchntSignInfoByPrimaryPK(String globalInstId, String mchntNo) throws Exception {
        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        return mchntInfoMapper.selectMchntSignInfoByPrimaryPK(globalInstId, mchntNo);
    }

    /**
     * 东营行商户重复入驻校验
     *
     * @param instId       成员行号
     * @param mchntNo      商户号
     * @param artifCertNo  证件号码
     * @param licenceCode  营业执照
     * @param settleAcctNo 结算账户
     * @return
     * @throws Exception
     */
    private List<TBMchntSignInfo> selectRepeatMchntBySignInfoForDY(String instId, String mchntNo, String artifCertNo, String licenceCode, String settleAcctNo) throws Exception {
        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        return mchntInfoMapper.selectRepeatMchntBySignInfo(instId, mchntNo, artifCertNo, licenceCode, settleAcctNo);
    }

    /**
     * 使用主键查询手续费减免活动商户统计表累计优惠金额数据库操作接口实现
     *
     * @param instId  法人机构号
     * @param mchntNo 商户编号
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt 手续费减免活动商户统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2021/5/28 14:55
     */
    private TMStatMfdMchnt selectMchntFeeTotalAmtMchntStatistics(String instId, String mchntNo) throws Exception {
        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectMchntFeeTotalAmtMchntStatistics(instId, mchntNo);
    }

    /**
     * 重新计算手续费
     *
     * @return int 返回码
     * @author liujinan
     * @since 2021/5/19 09:36
     */
    private boolean recalculateMchntFee(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, BigDecimal orderAmt, BigDecimal remainderDiscountAmt, PaymentOrderMchntFeeDiscountInfoBean feeOrderDetail, String newMchntFeeFlag) throws Exception {
        String instId = mcMchntFeeDiscountTransData.getInstId();
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();
        String feeType = mcMchntFeeDiscountTransData.getFeeType();
        //不可优惠交易金额
        BigDecimal noDiscountAmt = orderAmt.subtract(remainderDiscountAmt);
        rglog.info("商户<{}> 订单总金额<{}> 可优惠交易金额<{}> 不可优惠交易金额<{}>", mchntNo, orderAmt, remainderDiscountAmt, noDiscountAmt);

        String calMchntFeeBizeProdCode = mcMchntFeeDiscountTransData.getCalMchntFeeBizProdCode();
        //---计算不可优惠金额实际应该收的手续费
        if (null == feeType || null == calMchntFeeBizeProdCode) {
            rglog.error("商户<{}> 存在免充值的对客营销活动，营销需要重新计算手续费信息，费率类型和计算手续费产品编码必须上送！", mchntNo);
            throw new BizException(RespCodeEnum.REQUEST_PARAMETER_LOST.getRespCode(), RespCodeEnum.REQUEST_PARAMETER_LOST.getRespDesc());
        }
        CalcMchntFeeBean calcMchntFeeBean = new CalcMchntFeeBean();
        calcMchntFeeBean.setInstId(instId);
        calcMchntFeeBean.setMchntNo(mchntNo);
        calcMchntFeeBean.setTransAmt(noDiscountAmt.toString());
        calcMchntFeeBean.setIgasBizProdType(calMchntFeeBizeProdCode);
        calcMchntFeeBean.setSubProdType(feeType);
        calcMchntFeeBean.setStageCode("");
        calcMchntFeeBean.setStageNum("");
        CalcMchntFee calcMchntFee = new CalcMchntFee();
        CalcMchntFeeResultBean calcMchntFeeResultBean = calcMchntFee.calcPayFee(calcMchntFeeBean);
        if (null == calcMchntFeeResultBean) {
            rglog.error("计算商户手续费失败,instId:<{}>,mchntNo:<{}>,transAmt:<{}>", instId, mchntNo, noDiscountAmt.toString());
            return false;
        }

        //不可优惠金额应收的手续费
        String noDiscountAmtMchntFee = calcMchntFeeResultBean.getMchntFee();
        rglog.info("商户<{}> 不可优惠交易金额应收手续费为<{}> ", mchntNo, noDiscountAmtMchntFee);
        if (null != noDiscountAmtMchntFee) {
            //判断不可优惠金额应收手续费和原所有订单金额优惠手续费相同，则无需重新计算剩余可优惠金额优惠的手续费
            if (new BigDecimal(noDiscountAmtMchntFee).compareTo(new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeReceivable())) >= 0) {
                //剩余不可优惠金额应收手续费大于等于原总金额应收手续费，本笔交易实际无优惠手续费，只消耗优惠交易金额
                mcMchntFeeDiscountTransData.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT);
                mcMchntFeeDiscountTransData.setMchntFeeActual(mcMchntFeeDiscountTransData.getMchntFeeReceivable());
            } else {
                CalcMchntFeeBean calcDiscountMchntFeeBean = new CalcMchntFeeBean();
                calcDiscountMchntFeeBean.setInstId(instId);
                calcDiscountMchntFeeBean.setMchntNo(mchntNo);
                calcDiscountMchntFeeBean.setTransAmt(remainderDiscountAmt.toString());
                calcDiscountMchntFeeBean.setIgasBizProdType(calMchntFeeBizeProdCode);
                calcDiscountMchntFeeBean.setSubProdType(feeType);
                calcDiscountMchntFeeBean.setStageCode("");
                calcDiscountMchntFeeBean.setStageNum("");
                CalcMchntFeeResultBean calcDiscountMchntFeeResultBean = calcMchntFee.calcPayFee(calcDiscountMchntFeeBean);
                if (null == calcDiscountMchntFeeResultBean) {
                    rglog.error("计算商户优惠手续费失败,instId:<{}>,mchntNo:<{}>,transAmt:<{}>", instId, mchntNo, remainderDiscountAmt.toString());
                    return false;
                }

                //可优惠金额应收的手续费
                String discountAmtMchntFee = calcDiscountMchntFeeResultBean.getMchntFee();
                rglog.info("商户<{}> 可优惠交易金额应收手续费为<{}> ", mchntNo, discountAmtMchntFee);

                //如果可优惠金额应收的手续费为0，所以实际可优惠的金额是无需收取手续费的
                if (BigDecimal.ZERO.compareTo(new BigDecimal(discountAmtMchntFee)) == 0
                        && BigDecimal.ZERO.compareTo(new BigDecimal(noDiscountAmtMchntFee)) == 0) {
                    rglog.info("剩余可优惠的交易金额及剩余不可优惠金额应收手续费均为0");
                    mcMchntFeeDiscountTransData.setMchntFeeDiscount(mcMchntFeeDiscountTransData.getMchntFeeReceivable());
                    mcMchntFeeDiscountTransData.setMchntFeeActual(CommonConstant.ZERO_AMOUNT);
                } else if (BigDecimal.ZERO.compareTo(new BigDecimal(discountAmtMchntFee)) == 0) {
                    rglog.info("剩余可优惠的交易金额应收手续费为0");
                    mcMchntFeeDiscountTransData.setMchntFeeDiscount(new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeReceivable()).subtract(new BigDecimal(noDiscountAmtMchntFee)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
                    mcMchntFeeDiscountTransData.setMchntFeeActual(noDiscountAmtMchntFee);
                } else {
                    rglog.info("剩余可优惠的交易金额应收手续费不为0");
                    //如果是新商户，则可优惠金额直接免手续费，不需要通过规则计算优惠的手续费
                    if (CommonConstant.ONE_COMMON_CONSTANT.equals(newMchntFeeFlag)) {
                        rglog.info("商户<{}> 为新商户，剩余可优惠的交易金额直接免手续费，无需通过规则计算优惠值 ", mchntNo);
                        //如果可优惠金额应收的手续费为0，所以实际可优惠的金额是无需收取手续费的
                        rglog.info("剩余可优惠的交易金额不为0");
                        mcMchntFeeDiscountTransData.setMchntFeeDiscount(discountAmtMchntFee);
                        //计算实收的手续费
                        BigDecimal mchntFeeActual = new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeReceivable()).subtract(new BigDecimal(discountAmtMchntFee)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                        mcMchntFeeDiscountTransData.setMchntFeeActual(mchntFeeActual.toString());
                    } else {
                        rglog.info("剩余可优惠的交易金额不为0");
                        //存量商户获取计算规则，计算可优惠金额能够优惠的手续费
                        McMchntFeeDiscountTransData discountMcMchntFeeDiscountTransData = new McMchntFeeDiscountTransData();
                        discountMcMchntFeeDiscountTransData.setDiscountType(mcMchntFeeDiscountTransData.getDiscountType());
                        discountMcMchntFeeDiscountTransData.setMchntNo(mchntNo);
                        discountMcMchntFeeDiscountTransData.setMchntFeeReceivable(discountAmtMchntFee);
                        discountMcMchntFeeDiscountTransData.setMchntFeeReceivableRate(mcMchntFeeDiscountTransData.getMchntFeeReceivableRate());
                        discountMcMchntFeeDiscountTransData.setDiscount(mcMchntFeeDiscountTransData.getDiscount());

                        PaymentOrderMchntFeeDiscountInfoBean paymentOrderMchntFeeDiscountInfoBean = new PaymentOrderMchntFeeDiscountInfoBean();
                        paymentOrderMchntFeeDiscountInfoBean.setFeeInputMode(feeOrderDetail.getFeeInputMode());
                        paymentOrderMchntFeeDiscountInfoBean.setOrderAmt(remainderDiscountAmt.toString());
                        paymentOrderMchntFeeDiscountInfoBean.setMchntFeeReceivableRate(feeOrderDetail.getMchntFeeReceivableRate());
                        //根据营销活动规则计算可优惠金额的补贴减免金额
                        String subsidy = calculateMchntFeeDiscountSubsidy(discountMcMchntFeeDiscountTransData, paymentOrderMchntFeeDiscountInfoBean);
                        if (null == subsidy) {
                            rglog.info("商户<{}> 剩余可优惠的交易金额计算手续费优惠金额异常!", mchntNo);
                            return false;
                        } else {
                            BigDecimal zeroAmt = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            BigDecimal totalSubsidy = new BigDecimal(discountMcMchntFeeDiscountTransData.getMchntFeeDiscount()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                            if (CommonConstant.ZERO == zeroAmt.compareTo(totalSubsidy)) {
                                /* 优惠金额为0,不优惠商户手续费 */
                                rglog.info("通过计算商户<{}> 剩余可优惠交易金额的优惠手续费为0,不优惠,这种情况也消耗优惠交易金额!", mchntNo);
                                //剩余可优惠的交易金额没有优惠，本笔交易总体没有手续费优惠 ，只消耗优惠交易金额
                                mcMchntFeeDiscountTransData.setMchntFeeDiscount(CommonConstant.ZERO_AMOUNT);
                                mcMchntFeeDiscountTransData.setMchntFeeActual(mcMchntFeeDiscountTransData.getMchntFeeReceivable());
                            } else {
                                rglog.info("商户<{}> 可优惠交易金额的的手续费减免金额<{}>", mchntNo, totalSubsidy);
                                mcMchntFeeDiscountTransData.setMchntFeeDiscount(totalSubsidy.toString());
                                //计算实收的手续费
                                BigDecimal mchntFeeActual = new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeReceivable()).subtract(new BigDecimal(discountMcMchntFeeDiscountTransData.getMchntFeeDiscount())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                                mcMchntFeeDiscountTransData.setMchntFeeActual(mchntFeeActual.toString());
                            }
                        }
                    }
                }
            }
        } else {
            rglog.error("商户<{}> 计算不可优惠交易金额应收手续费，返回手续费错误", mchntNo);
            return false;
        }
        return true;
    }

    /**
     * 使用主键查询统计信息备份表最新一条数据
     *
     * @param instId
     * @param statType
     * @param statPrimaryKey
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdPeriod
     * @throws Exception
     * @author liujinan
     * @date 2021/7/9
     */
    private TMStatBak selectTMStatBakByStatPrimaryKey(String instId, String statType, String statPrimaryKey) throws Exception {

        TMStatBakMapper tmStatBakMapper = new TMStatBakMapperImpl();
        return tmStatBakMapper.selectTMStatBakByStatPrimaryKey(instId, statType, statPrimaryKey);
    }

    /**
     * 手续费减免活动周期统计数据赋值
     *
     * @param tmStatMfdPeriod 手续费减免活动周期统计表
     * @param tmStatMfdDay    手续费减免活动单日统计表
     * @author liujinan
     * @since 2021/7/12 11:23
     */
    private void copyMchntFeeDiscountMchntStatData(TMStatMfdPeriod tmStatMfdPeriod, TMStatMfdDay tmStatMfdDay) {

        /* 手续费减免活动周期统计表-累计优惠笔数 */
        tmStatMfdPeriod.setTotalQtyAcc(new BigDecimal(tmStatMfdPeriod.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTotalQtyAcc())).toString());
        /* 手续费减免活动周期统计表-累计优惠金额 */
        tmStatMfdPeriod.setTotalAmtAcc(new BigDecimal(tmStatMfdPeriod.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).toString());
        /* 手续费减免活动周期统计表-累计交易笔数 */
        tmStatMfdPeriod.setTxnQtyAcc(new BigDecimal(tmStatMfdPeriod.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTxnQtyAcc())).toString());
        /* 手续费减免活动周期统计表-累计交易金额 */
        tmStatMfdPeriod.setTxnAmtAcc(new BigDecimal(tmStatMfdPeriod.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTxnAmtAcc())).toString());
    }

    /**
     * 手续费减免活动周期统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfdPeriod 手续费减免活动周期统计表
     * @param tmStatMfdDay    手续费减免活动周期统计表
     * @author liujinan
     * @since 2021/7/12 11:22
     */
    private void copyMchntFeeDiscountPeriodZeroStatData(TMStatMfdPeriod tmStatMfdPeriod, TMStatMfdDay tmStatMfdDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {
        /* 手续费减免活动周期统计数据-周期内消耗金额 加本订单中参加相同活动的商户消耗预算（如果有，则在之前处理流程中已经更新到单日统计表中,此处与合并支付不同，合并支付是最后更新单日统计表），不加本明细手续费*/
        mcMchntFeeDiscountTransData.setPeriodTotalAmtAcc(new BigDecimal(tmStatMfdPeriod.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).toString());
    }

    /**
     * 检查营销活动状态
     * 商户手续费优惠类营销活动同时检查商户对应的当前交易日期是否在营销活动时间范围内
     *
     * @param mcMchntFeeDiscountTransData 数据入参对象
     * @return int 返回码
     * @author liujinan
     * @since 2021/7/15 10:00
     */
    private int checkMchntMcStatus(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 商户手续费优惠类营销活动 */
        String instId = mcMchntFeeDiscountTransData.getInstId();
        String mcStatus = mcMchntFeeDiscountTransData.getMcStatus();
        String mcStartDate = mcMchntFeeDiscountTransData.getMcStartDate();
        String mcEndDate = mcMchntFeeDiscountTransData.getMcEndDate();
        String mcNo = mcMchntFeeDiscountTransData.getMcNo();
        String mchntNo = mcMchntFeeDiscountTransData.getMchntNo();
        //存量商户判断
        if (CommonConstant.MCHNT_OLD_FLAG.equals(mcMchntFeeDiscountTransData.getNewMchntFlag())) {
            /* 判断营销活动状态是否是进行中 */
            if (!McStatusEnum.PROGRESSING.getMcStatusCode().equals(mcStatus) && !McStatusEnum.TESTING.getMcStatusCode().equals(mcStatus)) {
                rglog.error("活动状态不是进行中,存量商户不予优惠, INST_ID=<{}>, MC_NO=<{}>, MC_STATUS=<{}>", instId, mcNo, mcStatus);
                return CommonConstant.PROCESS_FAILED;
            }

            /* 检查商户手续费优惠累营销活动存量商户对应营销活动时间 */
            int returnCode = MompDateUtil.checkDateRange(globalTxnDate, mcStartDate, mcEndDate);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("当前交易日期<{}>未在营销活动的有效期<{}>-<{}>内,机构<{}>的存量商户<{}>不可参加营销活动<{}>",
                        globalTxnDate, mcStartDate, mcEndDate, instId, mchntNo, mcNo);
                return CommonConstant.PROCESS_FAILED;
            }
            return CommonConstant.PROCESS_SUCCESS;
        } else {//新商户判断活动状态
            /* 判断营销活动状态是否是进行中  商户已判断是否在优惠周期内  checkNewMchntAvailability方法*/
            if (McStatusEnum.PROGRESSING.getMcStatusCode().equals(mcStatus)) {
                rglog.info("活动状态为进行中，新商户给予优惠, INST_ID=<{}>, MC_NO=<{}>, MC_STATUS=<{}>", instId, mcNo, mcStatus);
                return CommonConstant.PROCESS_SUCCESS;
            } else if (McStatusEnum.ENDED.getMcStatusCode().equals(mcStatus)) {
                rglog.info("活动状态为自然结束，已判断活动是否支持顺延并且商户还在优惠周期内，新商户给予优惠, INST_ID=<{}>, MC_NO=<{}>, MC_STATUS=<{}>", instId, mcNo, mcStatus);
                return CommonConstant.PROCESS_SUCCESS;
            } else {
                rglog.info("活动状态为暂停或强制终止或其他状态，新商户不给予优惠, INST_ID=<{}>, MC_NO=<{}>, MC_STATUS=<{}>", instId, mcNo, mcStatus);
                return CommonConstant.PROCESS_FAILED;
            }
        }
    }

    /**
     * 手续费减免活动商户统计数据赋值
     *
     * @param tmStatMfdMchnt    手续费减免活动商户统计表
     * @param tmStatMfdMchntDay 手续费减免活动商户单日统计表
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyMchntStatMfdData(TMStatMfdMchnt tmStatMfdMchnt, TMStatMfdMchntDay tmStatMfdMchntDay) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTotalQtyAcc(new BigDecimal(tmStatMfdMchnt.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTotalAmtAcc(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTxnQtyAcc(new BigDecimal(tmStatMfdMchnt.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTxnAmtAcc(new BigDecimal(tmStatMfdMchnt.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }

    /**
     * 手续费减免活动统计数据赋值
     *
     * @param tmStatMfd    手续费减免活动统计表
     * @param tmStatMfdDay 手续费减免活动单日统计表
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyStatMfdData(TMStatMfd tmStatMfd, TMStatMfdDay tmStatMfdDay) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfd.setTotalQtyAcc(new BigDecimal(tmStatMfd.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTotalQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfd.setTotalAmtAcc(new BigDecimal(tmStatMfd.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfd.setTxnQtyAcc(new BigDecimal(tmStatMfd.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTxnQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfd.setTxnAmtAcc(new BigDecimal(tmStatMfd.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }

    /**
     * 使用商户号和商户所在商圈编号和活动号匹配营销活动商户信息表中数据
     *
     * @param instId    机构号
     * @param mchntNo   商户号
     * @param mchntArea 商圈号
     * @param mcNo      活动号
     * @return java.util.List<cc.rengu.igas.momp.common.entity.TMMcMchntInfo> 营销活动商户信息表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2021/9/2 15:10
     */
    private List<TMMcMchntInfo> matchMcMchntInfoByUsingMchntInfoAndMcNo(String instId, String mchntNo, String mchntArea, String mcNo) throws Exception {
        TBMchntBaseInfo mchntBaseInfo = new TBMchntBaseInfo();
        mchntBaseInfo.setInstId(instId);
        mchntBaseInfo.setMchntNo(mchntNo);
        mchntBaseInfo.setMchntArea(mchntArea);
        McMchntInfoMapper mcMchntInfoMapper = new McMchntInfoMapperImpl();
        return mcMchntInfoMapper.matchMoMcInfoByMchntNoAndMchntAreaAndMcNo(mchntBaseInfo, mcNo);
    }
}
